Verilog实现序列产生器(状态转移形,移位形,计数形)
Verilog实现序列产生器是Verilog基础学习甚至求职面试时的一个常见问题,它用到计数器、状态机、移位寄存器等一系列知识。因此有必要进行学习与仿真:
一、思路
状态转移形(利用状态机转移,逐个输出序列值);
移位寄存器形(输入整个序列,在时钟驱动下不断按顺序循环输出序列中的某一位,从而实现序列的循环输出);
计数形(计数与组合逻辑相结合,通过卡诺图化简得到计数值与输出的关系);
仿真:简单起见,假定实现1011序列
二、状态转移形式
采用思路一,设计状态机,实现几个状态循环转移的过程,每一个状态输出对应序列值,实现序列输出;
状态设置:
设置为四个状态,s0=2'b0、s1=2'b1、s2=2'b10、s3=2'b11(常见编码方式有二进制编码、格雷码、独热码,此处选为二进制码)
状态机设置:
三段式描述方式(时序逻辑描述状态转移、组合逻辑描述状态转移条件、时序逻辑描述输出)
Verilog代码如下:
-
`timescale 1ns / 1ps
-
//
-
// Company:
-
// Engineer: guoliang CLL
-
//
-
// Create Date: 2020/02/21 00:20:42
-
// Design Name:
-
// Module Name: seq_gen_fsm
-
// Project Name:
-
// Target Devices:
-
// Tool Versions:
-
// Description:
-
//
-
// Dependencies:
-
//
-
// Revision:
-
// Revision 0.01 - File Created
-
// Additional Comments:
-
//
-
//
-
module seq_gen_fsm(
-
input clk,
-
input rst_n,
-
output reg seq
-
);
-
// state declaration
-
parameter s0 = 2'b0,s1 = 2'b1,s2 = 2'b10,s3 = 2'b11;
-
reg [1:0]c_state,n_state;
-
// 状态转移
-
always@(posedge clk or negedge rst_n)
-
begin
-
if(!rst_n)
-
begin
-
c_state <= s0;
-
end
-
else
-
begin
-
c_state <= n_state;
-
end
-
end
-
// 状态转移条件
-
always@(c_state or rst_n)
-
begin
-
if(!rst_n)
-
begin
-
n_state = s0;
-
end
-
else
-
begin
-
case(c_state)
-
s0:n_state = s1;
-
s1:n_state = s2;
-
s2:n_state = s3;
-
s3:n_state = s0;
-
default:n_state = s0;
-
endcase
-
end
-
end
-
// 输出
-
always@(posedge clk or negedge rst_n)
-
begin
-
if(!rst_n)
-
begin
-
seq <= 1'b0;
-
end
-
else
-
begin
-
case(n_state)
-
s0:seq <= 1'b1;
-
s1:seq <= 1'b0;
-
s2:seq <= 1'b1;
-
s3:seq <= 1'b1;
-
default:seq <= 1'b0;
-
endcase
-
end
-
end
-
endmodule
测试代码如下:
-
`timescale 1ns / 1ps
-
//
-
// Company:
-
// Engineer:
-
// Create Date: 2020/02/21 00:35:17
-
// Design Name:
-
// Module Name: seq_gen_tsb
-
// Project Name:
-
// Target Devices:
-
// Tool Versions:
-
// Description:
-
// Dependencies:
-
// Revision:
-
// Revision 0.01 - File Created
-
// Additional Comments:
-
module seq_gen_tsb(
-
);
-
// port
-
reg clk;
-
reg rst_n;
-
wire seq;
-
// clk
-
initial
-
begin
-
clk = 1'b1;
-
forever #10 clk = ~clk;
-
end
-
initial
-
begin
-
rst_n = 1'b1;
-
#20 rst_n = 1'b0;
-
#50 rst_n = 1'b1;
-
end
-
// instantation
-
seq_gen_fsm inst(
-
.clk(clk),
-
.rst_n(rst_n),
-
.seq(seq)
-
);
-
endmodule
输出波形如下:
RTL电路如下:
三、循环移位形式:
利用循环移位寄存器,每个时钟移位一次,也可以很简单的实现序列产生
实现代码如下:
-
`timescale 1ns / 1ps
-
//
-
// Company:
-
// Engineer:
-
//
-
// Create Date: 2020/02/21 00:58:25
-
// Design Name:
-
// Module Name: seq_gen_shift
-
// Project Name:
-
// Target Devices:
-
// Tool Versions:
-
// Description:
-
//
-
// Dependencies:
-
//
-
// Revision:
-
// Revision 0.01 - File Created
-
// Additional Comments:
-
//
-
//
-
module seq_gen_shift(
-
input clk,
-
input rst_n,
-
output seq
-
);
-
// sequence declaration
-
reg [3:0]SEQ = 4'b1011;
-
//
-
always@(posedge clk or negedge rst_n)
-
begin
-
if(!rst_n)
-
SEQ <= 4'b1011;
-
else
-
SEQ <= {SEQ[2:0],SEQ[3]};
-
end
-
assign seq = SEQ[3];
-
endmodule
测试文件不变
输出如下:
RTL电路如下:
四、计数器译码形式
设计4值的循环计数器,在此基础上对计数进行译码(可以case选择,也可以与或非描述),不同计数值时输出不同序列值,即可实现序列产生;
实现代码如下:
-
`timescale 1ns / 1ps
-
//
-
// Company:
-
// Engineer:
-
//
-
// Create Date: 2020/02/21 01:19:15
-
// Design Name:
-
// Module Name: seq_gen_count
-
// Project Name:
-
// Target Devices:
-
// Tool Versions:
-
// Description:
-
//
-
// Dependencies:
-
//
-
// Revision:
-
// Revision 0.01 - File Created
-
// Additional Comments:
-
//
-
//
-
module seq_gen_count(
-
input clk,
-
input rst_n,
-
output seq
-
);
-
reg [1:0]count;
-
always@(posedge clk or negedge rst_n)
-
begin
-
if(!rst_n)
-
count <= 2'b0;
-
else if(count == 2'b11)
-
count <= 2'b0;
-
else
-
count <= count+2'b1;
-
end
-
// out
-
assign seq = (count[1]&count[0]) | (!count[1]&!count[0]) | (count[1]&!count[0]);
-
endmodule
测试代码不变
输出如下:
RTL电路如下: