暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

数字IC校招手撕代码: 可参数化的多端口寄存器堆设计

IC墨鱼仔 2022-09-26
688

题目

用Verilog设计一个可参数化的寄存器堆,同一时刻输入的写地址互不相同,但读地址可以相同,所有端口都能连续响应读写请求


分析

用Verilog实现,不断寻找序列中的第一个1,并输出其index,当寻找完毕后输出结束信号。(以LSB为例)

  • 首先题目要求了是可参数化多端口寄存器堆,需要通过多个端口对寄存器堆读写,这势必要用for循环的方式完成;

  • 其次要根据en、wr信号进行读写状态的区分;

  • 在本题中最为关键的其实是写状态时,din向缓冲区传输的过程,很多朋友可能都会是下列的做法。

    genvar i;
    generate
    for(i=0;i<PORT;i++)begin
     always @(posedge clk or negedge rst_n)begin
       if(!rst_n)begin
         for(integer j=0;j<DEPTH;j++)
           data[j][WIDTH-1:0] <{(WIDTH){1'b0}};
       end
       else if(en[i] & wr[i])
         data[addr[i][WIDTH-1:0] <= din[i][WIDTH-1:0];
     end
    end
    endgenerate

    上述代码乍一看好像没什么问题,输入也保证了写地址不会相同,但其实data上存在multi drive的问题,电路的角度上是确实存在多个数据同时向同一寄存器写入的问题。

      所以需要对din提前mux处理,再将mux的结果写入寄存器,这样才能完美的避免multi drive。


    代码

      module register_file(
      clk,
      rst_n,
      en,
      wr,
      addr,
      din,
      dout
      );


      parameter       PORT    =   2;
      parameter       WIDTH   =   32;
      parameter       DEPTH   =   128;
      parameter       DEPTH_L =   log2(DEPTH);


      input                               clk;
      input                               rst_n;
      input   [PORT-1:0]                  en;
      input   [PORT-1:0]                  wr;
      input   [PORT-1:0][DEPTH_L-1:0]     addr;
      input   [PORT-1:0][WIDTH-1:0]       din;
      output  [PORT-1:0][WIDTH-1:0]       dout;




      wire    [DEPTH-1:0][PORT-1:0]   wr_hit;
      wire    [DEPTH-1:0][WIDTH-1:0]  din_mux;
      reg     [DEPTH-1:0][WIDTH-1:0]  data;
      reg     [PORT-1:0][WIDTH-1:0]   dout;




      genvar g,h;


      generate
         for(g=0;g<DEPTH;g++)begin
             for(h=0;h<PORT;h++)begin
                 assign wr_hit[g][h] = en[h] & wr[h] &(addr[h]==g);
             end


             one_hot_mux_2d #(
                 .WIDTH(WIDTH),
                 .CNT(PORT)
             ) one_hot_mux(
                 .din(din),
                 .sel(wr_hit[g]),
                 .dout(din_mux[g])
             );
         end
      endgenerate




      always @(posedge clk or negedge rst_n)begin
         integer i;
         if(!rst_n)begin
             for(i=0;i<DEPTH;i++)
                 data[i] <= {(WIDTH){1'b0}};
         end
         else begin
             for(i=0;i<DEPTH;i++)begin
                 if(wr_hit[i])
                     data[i] <= din_mux[i];
             end
         end
      end




      always @(posedge clk or negedge rst_n)begin
         integer i;
         if(!rst_n)begin
             for(i=0;i<PORT;i++)
                 dout[i] <= {(WIDTH){1'b0}};
         end
         else begin
             for(i=0;i<PORT;i++)
                 dout[i] <= data[addr[i]];
         end
      end


      endmodule






      文章转载自IC墨鱼仔,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

      评论