查看: 1156|回复: 0
收起左侧

E203 同步fifo

[复制链接]

  离线 

  • TA的每日心情
    奋斗
    2021-3-3 12:32
  • 签到天数: 10 天

    [LV.3]

    发表于 2021-3-6 14:34:57 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    1. 输入端,
          输入信号, i_vld,表示输入请求写同步fifo,如果fifo不满,则fifo发送i_rdy 到输入端,开始写fifo。i_vld和i_rdy是写握手信号。

    2.输出端
          o_rdy表示接受端已经准备好了,可以读取fifo,o_vld表示fifo准备好了,不为空,可以输出到接收端。o_rdy和o_vld是握手信号。

    3.如果fifo是深度为0,则是bypass模式,只要请求写,就直接准备输出,所以

    assign o_vld = i_vld;
    assign i_rdy = o_rdy;
    assign o_dat = i_dat;

    可以立即发送数据 o_dat=idat, 对于深度为n的情况, i_rdy = ~full, o_vld=~empty, 就是i_rdy和o_vld是满空标志取反。

    国内芯片技术交流-E203 同步fiforisc-v单片机中文社区(1)


    4.如果深度为n,假设为4, 我们设置i_vld=1,但是o_rdy 总是0,则输入端写fifo,直到fifo满。

    testbench代码如下:
    1. module sirv_gnrl_dffs_tb;

    2.    reg  clk=0,rst_n;
    3.    reg  i_vld, o_rdy;
    4.    reg  [31:0] i_dat;

    5.    wire i_rdy, o_vld;
    6.    wire [31:0] o_dat;

    7.    sirv_gnrl_fifo  #(.CUT_READY(1),.DP(4),.DW(32)) mybuf(.i_vld(i_vld),.i_rdy(i_rdy),.i_dat(i_dat),.o_vld(o_vld),.o_rdy(o_rdy),.o_dat(o_dat),.clk(clk),.rst_n(rst_n));

    8.    always #10 clk=~clk;

    9.    initial
    10.    begin
    11.         rst_n=1'b1;
    12.         i_vld = 1'b0;
    13.         o_rdy = 1'b0;
    14.         i_dat = 32'h12345678;
    15.         #20
    16.         rst_n=1'b0;
    17.         #80
    18.         rst_n=1'b1;
    19.         #80
    20.         i_vld = 1'b1;
    21.         o_rdy = 1'b0;
    22.         i_dat = $random()%32;
    23.         #80
    24.         i_vld = 1'b1;
    25.         o_rdy = 1'b0;
    26.         i_dat = $random()%32;
    27.         #20
    28.         i_vld = 1'b0;
    29.         o_rdy = 1'b0;
    30.         i_dat = $random()%32;
    31.         #20
    32.         i_vld = 1'b1;
    33.         o_rdy = 1'b0;
    34.         i_dat = $random()%32;
    35.         #20
    36.         i_vld = 1'b1;
    37.         o_rdy = 1'b0;
    38.         i_dat = $random()%32;
    39.         #20
    40.         i_vld = 1'b1;
    41.         o_rdy = 1'b0;
    42.         i_dat = $random()%32;
    43.         #20
    44.         i_vld = 1'b1;
    45.         o_rdy = 1'b0;
    46.         i_dat = $random()%1024;
    47.         #20
    48.         i_vld = 1'b1;
    49.         o_rdy = 1'b0;
    50.         i_dat = $random()%1024;
    51.         #20
    52.         i_vld = 1'b1;
    53.         o_rdy = 1'b0;
    54.         i_dat = $random()%1024;
    55.         #20
    56.         i_vld = 1'b1;
    57.         o_rdy = 1'b0;
    58.         i_dat = $random()%1024;
    59.         #20
    60.         #20
    61.         i_vld = 1'b1;
    62.         o_rdy = 1'b0;
    63.         i_dat = $random()%1024;
    64.         #500 $finish;
    65.    end

    66.    initial
    67.            $monitor($time,,,"clk=%b,rst_n=%b,i_vld=%b,o_rdy=%b, i_rdy=%b, o_vld=%b,",clk,rst_n,i_vld,o_rdy,i_rdy,o_vld);
    68.    initial
    69.    begin
    70.            //$dumpfile("dump.vcd");
    71.            //$dumpvars;
    72.            $fsdbDumpfile("dump.fsdb");
    73.         $fsdbDumpvars("+all");
    74.    end



    75.    endmodule
    复制代码


    国内芯片技术交流-E203 同步fiforisc-v单片机中文社区(2)


    初始时刻,同步fifo各个信号都是x,直到复位信号rst_n的下降沿到来时候,复位读写指针触发器和向量寄存器触发器,向量寄存器主要用于空满判断。

    读写指针都被初始化为1,如果fifo深度(DP)=1,则读写指针rptr_vec_r,wptr_vec_r总是1

    下一个读写指针rptr_vec_nxt/wptr_vec_nxt 等于当前指针左移一位,假设DP=4,则指针为0001,0010,0100,1000, 1000的下一个是0001,首尾相接。

    这种表示法是用独热码的方式表示读写指针。

    1. ////////////////
    2.     ///////// Read-Pointer and Write-Pointer
    3.     // if ith is 1, then means read/write ith value of fifo
    4.     wire [DP-1:0] rptr_vec_nxt;
    5.     wire [DP-1:0] rptr_vec_r;
    6.     wire [DP-1:0] wptr_vec_nxt;
    7.     wire [DP-1:0] wptr_vec_r;
    8.     //read pointer dynamic process,
    9.     // always is 1
    10.     if(DP == 1) begin:rptr_dp_1
    11.       assign rptr_vec_nxt = 1'b1;
    12.     end
    13.     else begin:rptr_dp_not_1   // 0001,0010,0100,1000,0001, ring buffer,
    14.       assign rptr_vec_nxt =
    15.           rptr_vec_r[DP-1] ? {{DP-1{1'b0}}, 1'b1} :
    16.                           (rptr_vec_r << 1);
    17.     end

    18.     if(DP == 1) begin:wptr_dp_1
    19.       assign wptr_vec_nxt = 1'b1;
    20.     end
    21.     else begin:wptr_dp_not_1
    22.       assign wptr_vec_nxt =
    23.           wptr_vec_r[DP-1] ? {{DP-1{1'b0}}, 1'b1} :
    24.                           (wptr_vec_r << 1);
    25.     end
    复制代码

    向量寄存器触发器为DP+1位。复位下降沿道来时候,vec_r=1, 如果读和写有一个工作的时候,则vec_en=1。

    如果写enable的时候,vec_nxt = {vec_r[DP-1:0],1’b1},

    vec_r, vec_nxt:
    1,    11
    11,111
    111, 1111
    1111, 1_1111
    i_rdy = (~i_vec[DP-1]);

    如果i_vec[DP-1]=1,则表示fifo满了, i_rdy=0,此时不能写fifo了。

    1. ///////// Vec register to easy full and empty and the o_vld generation with flop-clean
    2.     wire [DP:0] i_vec;
    3.     wire [DP:0] o_vec;
    4.     wire [DP:0] vec_nxt;
    5.     wire [DP:0] vec_r;

    6.     wire vec_en = (ren ^ wen );//ren not same as wen set to 1
    7.     assign vec_nxt = wen ? {vec_r[DP-1:0], 1'b1} : (vec_r >> 1);

    8.     sirv_gnrl_dfflrs #(1)  vec_0_dfflrs     (vec_en, vec_nxt[0]     , vec_r[0]     ,     clk, rst_n);
    9.     sirv_gnrl_dfflr  #(DP) vec_31_dfflr     (vec_en, vec_nxt[DP:1], vec_r[DP:1],     clk, rst_n);

    10.     assign i_vec = {1'b0,vec_r[DP:1]};
    11.     assign o_vec = {1'b0,vec_r[DP:1]};
    复制代码

    会根据wen和写指针wptr_vec_r,把i_dat写入到指定的位置,因为是读热码,所以只有一位为1,为1的位置正好是fifo中最上面空的位置。

    1. ///////// write fifo
    2.     for (i=0; i<DP; i=i+1) begin:fifo_rf//{
    3.       assign fifo_rf_en[i] = wen & wptr_vec_r[i];
    4.       // Write the FIFO registers
    5.       sirv_gnrl_dffl  #(DW) fifo_rf_dffl (fifo_rf_en[i], i_dat, fifo_rf_r[i], clk);
    6.     end//}
    复制代码

    对于这个test,会在连续的4个时钟上升沿写入i_dat,因为此时i_dat都为4,所以会写入四个4。

    我们修改testbench,增加enable o_rdy

    1. module sirv_gnrl_dffs_tb;

    2.    reg  clk=0,rst_n;
    3.    reg  i_vld, o_rdy;
    4.    reg  [31:0] i_dat;

    5.    wire i_rdy, o_vld;
    6.    wire [31:0] o_dat;

    7.    sirv_gnrl_fifo  #(.CUT_READY(1),.DP(4),.DW(32)) mybuf(.i_vld(i_vld),.i_rdy(i_rdy),.i_dat(i_dat),.o_vld(o_vld),.o_rdy(o_rdy),.o_dat(o_dat),.clk(clk),.rst_n(rst_n));

    8.    always #10 clk=~clk;

    9.    initial
    10.    begin
    11.         rst_n=1'b1;
    12.         i_vld = 1'b0;
    13.         o_rdy = 1'b0;
    14.         i_dat = 32'h12345678;
    15.         #20
    16.         rst_n=1'b0;
    17.         #80
    18.         rst_n=1'b1;
    19.         #80
    20.         i_vld = 1'b1;
    21.         o_rdy = 1'b0;
    22.         i_dat = 32'h8;
    23.         #20
    24.         i_vld = 1'b1;
    25.         o_rdy = 1'b0;
    26.         i_dat = 32'h12;
    27.         #20
    28.         i_vld = 1'b1;
    29.         o_rdy = 1'b0;
    30.         i_dat = 32'h2;
    31.         #20
    32.         i_vld = 1'b1;
    33.         o_rdy = 1'b0;
    34.         i_dat = 32'h11;
    35.         #20
    36.         i_vld = 1'b1;
    37.         o_rdy = 1'b0;
    38.         i_dat = 32'h13;
    39.         #20
    40.         i_vld = 1'b0;
    41.         o_rdy = 1'b0;
    42.         i_dat = 32'h6;
    43.         #20
    44.         i_vld = 1'b0;
    45.         o_rdy = 1'b0;
    46.         i_dat = 32'h22;
    47.         #20
    48.         i_vld = 1'b0;
    49.         o_rdy = 1'b0;
    50.         i_dat = 32'h99;
    51.         #20
    52.         i_vld = 1'b0;
    53.         o_rdy = 1'b1;
    54.         i_dat = 32'h33;
    55.         #20
    56.         i_vld = 1'b0;
    57.         o_rdy = 1'b1;
    58.         i_dat = 32'h17;
    59.         #20
    60.         i_vld = 1'b0;
    61.         o_rdy = 1'b1;
    62.         i_dat = 32'h3;
    63.         #500 $finish;
    64.    end

    65.    initial
    66.            $monitor($time,,,"clk=%b,rst_n=%b,i_vld=%b,o_rdy=%b, i_rdy=%b, o_vld=%b,",clk,rst_n,i_vld,o_rdy,i_rdy,o_vld);
    67.    initial
    68.    begin
    69.            //$dumpfile("dump.vcd");
    70.            //$dumpvars;
    71.            $fsdbDumpfile("dump.fsdb");
    72.         $fsdbDumpvars("+all");
    73.    end



    74.    endmodule
    复制代码

    国内芯片技术交流-E203 同步fiforisc-v单片机中文社区(3)

    // o_vld as flop-clean
    assign o_vld = (o_vec[0]);


    根据o_vec[0]判断是否为空,如果不为空,则enable o_vld,开始读fifo。

    根据当前的读指针,从fifo中取出数据,并赋值给o_dat, 如果设置了mask out,会把数据初始值中的x mask掉。默认设置这个值。

    1. /////////One-Hot Mux as the read path
    2.     integer j;
    3.     reg [DW-1:0] mux_rdat;
    4.     always @*
    5.     begin : rd_port_PROC//{
    6.       mux_rdat = {DW{1'b0}};
    7.       for(j=0; j<DP; j=j+1) begin
    8.         mux_rdat = mux_rdat | ({DW{rptr_vec_r[j]}} & fifo_rf_r[j]);
    9.       end
    10.     end//}

    11.     if(MSKO == 1) begin:mask_output//{
    12.         // Mask the data with valid since the FIFO register is not reset and as X
    13.         assign o_dat = {DW{o_vld}} & mux_rdat;
    14.     end//}

    15. else begin:no_mask_output//{
    16.      // Not Mask the data with valid since no care with X for datapth
    17.      assign o_dat = mux_rdat;
    18. end//}
    复制代码

    再看下CUT_READY, 当fifo深度为1的时候,ready和下一个阶段的ready信号相关,变成了逻辑链。我们可以通过CUT_READY来控制它。

    如果设置了CUT_READY,仅当fifo不为空的时候,才能设置i_rdy信号,可以切断反压信号,阻止它传递到上一级,这时候2个周期传输一个数据。如果设置CUT_READY=0,则变成一个popping操作,同一个周期放入弹出。

    1. if(DP == 1) begin:cut_dp_eq1//{
    2.         if(CUT_READY == 1) begin:cut_ready//{
    3.           // If cut ready, then only accept when fifo is not full
    4.           assign i_rdy = (~i_vec[DP-1]);
    5.         end//}
    6.         else begin:no_cut_ready//{
    7.           // If not cut ready, then can accept when fifo is not full or it is popping
    8.           assign i_rdy = (~i_vec[DP-1]) | ren;
    9.         end//}
    10.     end//}
    11.     else begin : no_cut_dp_gt1//}{
    12.       assign i_rdy = (~i_vec[DP-1]);
    13.     end//}
    复制代码

    下面是DP=1,设置CUT_READY=1 和0的波形。

    CUT_READY=1

    国内芯片技术交流-E203 同步fiforisc-v单片机中文社区(4)



    CUT_READY=0

    国内芯片技术交流-E203 同步fiforisc-v单片机中文社区(5)






    上一篇:memory一致性模型
    下一篇:E203 bypass buffer
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-3-28 23:24 , Processed in 0.595042 second(s), 48 queries .

    快速回复 返回顶部 返回列表