mir_cs的个人空间 https://blog.eetop.cn/1826108 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

2024-08-07

已有 229 次阅读| 2024-8-7 10:47 |个人分类:一些设计概念探索|系统分类:芯片设计


序列生成

定义:顾名思义,就是稳定发送一串序列出去。

分类:状态机、移位寄存器、移位寄存器+组合逻辑、计数器+组合逻辑

原理:

1.状态机

这个就不仔细说了,采用Moore状态机,寻找最短循环节,然后针对最短循环节中的每一位设置一个状态,再加上一个IDLE状态即可完成设计(其实完全用不上这个IDLE状态,不过如果想做控制逻辑,即需要加入使能信号,则应该尽量加上IDLE状态)。以下代码以生成“101011”为例。

verilog;toolbar:false">module sequence_generator_fsm (
    //input
    clk             ,
    rstn            ,
    //output
    seq_o
);

// ------------------ PARAM ---------------------
    localparam  FSM_WD                              =   'd3;
    localparam  IDLE                                =   3'd0;
    localparam  T_1                                 =   3'd1;
    localparam  T_2                                 =   3'd2;
    localparam  T_3                                 =   3'd3;
    localparam  T_4                                 =   3'd4;
    localparam  T_5                                 =   3'd5;
    localparam  T_6                                 =   3'd6;

// ------------------ IO -----------------------
    input                                           clk;
    input                                           rstn;
    output reg                                      seq_o;

// ------------------ WIRE ---------------------

// ------------------ REG ----------------------
    reg        [FSM_WD                    -1 :0]    cur_state_r                    ;
    reg        [FSM_WD                    -1 :0]    nxt_state_r                    ;
// ------------------ GVAR ---------------------

// ---------------- MAIN BODY ------------------
//--- FSM ----
    // cur_state_r
    always @(posedge clk or negedge rstn) begin
        if( !rstn )
            cur_state_r <= T_1;
        else
            cur_state_r <= nxt_state_r;
    end

    // nxt_state_r
    always @(*) begin
        nxt_state_r = IDLE;
        case( cur_state_r )
            IDLE: nxt_state_r = T_1;
            T_1 : nxt_state_r = T_2;
            T_2 : nxt_state_r = T_3;
            T_3 : nxt_state_r = T_4;
            T_4 : nxt_state_r = T_5;
            T_5 : nxt_state_r = T_6;
            T_6 : nxt_state_r = T_1;
            default : nxt_state_r = IDLE;
        endcase
    end
//--- output ----
    always @(*) begin
        case( cur_state_r )
            IDLE: seq_o = 'd0;
            T_1 : seq_o = 'd1;
            T_2 : seq_o = 'd0;
            T_3 : seq_o = 'd1;
            T_4 : seq_o = 'd0;
            T_5 : seq_o = 'd1;
            T_6 : seq_o = 'd1;
            default : seq_o = 'd0;
        endcase
    end

endmodule

2.移位寄存器

这个也是先寻找最短循环节,假设其有N位,则移位寄存器也设置为N位。然后在清零时写入待生成的序列,之后即可使用向左/向右移位完成生成序列的目的。注意这个逻辑同样会被应用于并转串模块的逻辑。

module sequence_generator_shift (
    //input
    clk             ,
    rstn            ,
    //output
    seq_o
);

// ------------------ PARAM ---------------------
    localparam  SFT_WD                              =   'd6;

// ------------------ IO -----------------------
    input                                           clk;
    input                                           rstn;
    output                                          seq_o;

// ------------------ WIRE ---------------------

// ------------------ REG ----------------------
    reg        [SFT_WD                    -1 :0]    shift_r                    ;
// ------------------ GVAR ---------------------

// ---------------- MAIN BODY ------------------
    always @(posedge clk or negedge rstn) begin
        if( !rstn )
            shift_r <= 6'b101011;
        else
            shift_r <= {shift_r[SFT_WD-2:0], shift_r[SFT_WD-1]};
    end

    assign seq_o = shift_r[SFT_WD-1];

endmodule

3.移位寄存器+组合逻辑

这个是本科阶段数电课上的内容,使用组合逻辑换取移位寄存器长度的方法。其基本结构与2的移位寄存器类似,不过其需要使用后续移位寄存器输出来定义一个组合逻辑作为第一级的输入。此时经过证明,移位寄存器长度至少为N/2[请求来源],而这里如果长度取3,则会出现两个“101”状态同时对应着0和1,故应该使用4长度。还是以101011为例,将每位寄存器的输出Q视作其状态,作出其状态转换表:(F->Q0->Q1->Q2->Q3)

F(第一级输入)Q0Q1Q2Q3(输出)
10101
11010
11101
01110
10111
01011

于是可以作出第一级输入的卡诺图:

Q3Q2\Q1Q000011110
00xxxx
01x10x
11x0x1
10xx11

其中x代表不关心的值。根据数电处理卡诺图的方法,可以知道F=Q3Q1+(~Q3)(~Q1)=~(Q3^Q1)(其中^代表异或逻辑,~代表非逻辑)因此便可得到其结构,并可根据结构写出代码:

module sequence_generator_shift_comb (
    //input
    clk             ,
    rstn            ,
    //output
    seq_o
);

// ------------------ PARAM ---------------------
    localparam  SFT_WD                              =   'd4;

// ------------------ IO -----------------------
    input                                           clk;
    input                                           rstn;
    output                                          seq_o;

// ------------------ WIRE ---------------------
    wire                                            shift_w                    ;

// ------------------ REG ----------------------
    reg        [SFT_WD                    -1 :0]    shift_r                    ;
// ------------------ GVAR ---------------------

// ---------------- MAIN BODY ------------------
    always @(posedge clk or negedge rstn) begin
        if( !rstn )
            shift_r <= 4'b1010;
        else
            shift_r <= {shift_r[2:0], shift_w};
    end

    assign shift_w = ~(shift_r[3] ^ shift_r[1]);
    assign seq_o = shift_r[3];

endmodule

注意在上面的代码中,初始化使用的是第一个状态Q3Q2Q1Q0=1010,其实使用任何一个状态转换表中的状态都可以自启成功。

4.计数器+组合逻辑

这个基本的逻辑也很直观,计数器会一直进行计数,其长度为ceil(log2(N))(ceil()代表向上取整)位,并根据计数器输出通过组合逻辑设置其最终输出。还是以101011为例,由于ceil(log2(6))=3,故需要三位计数器。计数器从0计数到5,然后清零计数器。其输出设置如下:

Q2Q1Q0Y
0001
0010
0101
0110
1001
1011

于是可以作出输出的卡诺图:

Q2\Q1Q000011110
01001
111xx

根据数电处理卡诺图的方法,可以知道Y=~(Q0)+Q2。因此便可得到其结构,并可根据结构写出代码:

module sequence_generator_count_comb (
    //input
    clk             ,
    rstn            ,
    //output
    seq_o
);

// ------------------ PARAM ---------------------
    localparam  SFT_WD                              =   'd3;

// ------------------ IO -----------------------
    input                                           clk;
    input                                           rstn;
    output                                          seq_o;

// ------------------ WIRE ---------------------

// ------------------ REG ----------------------
    reg        [SFT_WD                    -1 :0]    cnt_r                    ;
// ------------------ GVAR ---------------------

// ---------------- MAIN BODY ------------------
    always @(posedge clk or negedge rstn) begin
        if( !rstn )
            cnt_r <= 'd0;
        else begin
            if( cnt_r == 'd5)
                cnt_r <= 'd0;
            else
                cnt_r <= cnt_r + 'd1;
        end
    end

    assign seq_o = (~cnt_r[0]) | cnt_r[2];

endmodule

仿真:

祖传testbench:

`timescale 1ns / 1ns

module tst_ripe_code;

// ------------------ IO -----------------------
    reg                                           clk;
    reg                                           rstn;
    wire                                          seq_w1_o;
    wire                                          seq_w2_o;
    wire                                          seq_w3_o;
    wire                                          seq_w4_o;

// ------------------ WIRE ---------------------

// ------------------ REG ----------------------

// ------------------ GVAR ---------------------

// ------------------ INTEGAR ---------------------


// ---------------- MAIN BODY ------------------
always #5 clk = ~clk;
initial begin
    rstn   = 'd0;
    clk   = 'd0;
   
    #10 rstn   = 'd1;
end

// ------------------ INST ---------------------
sequence_generator_fsm test_module_1(
    // input
  .clk             (clk       ),
  .rstn            (rstn      ),
    //output
  .seq_o           (seq_w1_o  )
);

sequence_generator_shift test_module_2(
    // input
  .clk             (clk       ),
  .rstn            (rstn      ),
    //output
  .seq_o           (seq_w2_o  )
);

sequence_generator_shift_comb test_module_3(
    // input
  .clk             (clk       ),
  .rstn            (rstn      ),
    //output
  .seq_o           (seq_w3_o  )
);

sequence_generator_count_comb test_module_4(
    // input
  .clk             (clk       ),
  .rstn            (rstn      ),
    //output
  .seq_o           (seq_w4_o  )
);

endmodule

仿真结果:

image.png


点赞

全部作者的其他最新日志

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 0

    粉丝
  • 0

    好友
  • 1

    获赞
  • 0

    评论
  • 1

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-9-27 11:45 , Processed in 0.025436 second(s), 18 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部