题目
用verilog设计一个可参数化的寄存器堆,同一时刻输入的写地址互不相同,但读地址可以相同,所有端口都能连续响应读写请求。
分析
- 首先题目要求了是可参数化的多端口寄存器堆,需要通过多个端口对寄存器堆读写,这势必要用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
版权声明:本文为sz_woshishazi原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。