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

输出波形如下:

Verilog实现序列产生器(状态转移形,移位形,计数形)_第1张图片

RTL电路如下:

Verilog实现序列产生器(状态转移形,移位形,计数形)_第2张图片

三、循环移位形式:

利用循环移位寄存器,每个时钟移位一次,也可以很简单的实现序列产生

实现代码如下:

`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

测试文件不变

输出如下:

Verilog实现序列产生器(状态转移形,移位形,计数形)_第3张图片

RTL电路如下:

Verilog实现序列产生器(状态转移形,移位形,计数形)_第4张图片

四、计数器译码形式

设计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

测试代码不变

输出如下:

Verilog实现序列产生器(状态转移形,移位形,计数形)_第5张图片

RTL电路如下:

Verilog实现序列产生器(状态转移形,移位形,计数形)_第6张图片

五、参考文献:

有重叠与无重叠序列之序列检测与序列产生

序列信号产生器的verilog HDL 设计

你可能感兴趣的:(FPGA/Verilog基础)