题目
用Verilog设计一个可参数化的寄存器堆,同一时刻输入的写地址互不相同,但读地址可以相同,所有端口都能连续响应读写请求。
分析
用Verilog实现,不断寻找序列中的第一个1,并输出其index,当寻找完毕后输出结束信号。(以LSB为例)
首先题目要求了是可参数化的多端口寄存器堆,需要通过多个端口对寄存器堆读写,这势必要用for循环的方式完成;
其次要根据en、wr信号进行读写状态的区分;
在本题中最为关键的其实是写状态时,din向缓冲区传输的过程,很多朋友可能都会是下列的做法。
genvar i;generatefor(i=0;i<PORT;i++)beginalways @(posedge clk or negedge rst_n)beginif(!rst_n)beginfor(integer j=0;j<DEPTH;j++)data[j][WIDTH-1:0] <{(WIDTH){1'b0}};endelse if(en[i] & wr[i])data[addr[i][WIDTH-1:0] <= din[i][WIDTH-1:0];endendendgenerate
上述代码乍一看好像没什么问题,输入也保证了写地址不会相同,但其实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;generatefor(g=0;g<DEPTH;g++)beginfor(h=0;h<PORT;h++)beginassign wr_hit[g][h] = en[h] & wr[h] &(addr[h]==g);endone_hot_mux_2d #(.WIDTH(WIDTH),.CNT(PORT)) one_hot_mux(.din(din),.sel(wr_hit[g]),.dout(din_mux[g]));endendgeneratealways @(posedge clk or negedge rst_n)begininteger i;if(!rst_n)beginfor(i=0;i<DEPTH;i++)data[i] <= {(WIDTH){1'b0}};endelse beginfor(i=0;i<DEPTH;i++)beginif(wr_hit[i])data[i] <= din_mux[i];endendendalways @(posedge clk or negedge rst_n)begininteger i;if(!rst_n)beginfor(i=0;i<PORT;i++)dout[i] <= {(WIDTH){1'b0}};endelse beginfor(i=0;i<PORT;i++)dout[i] <= data[addr[i]];endendendmodule

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




