regs.v寄存器
32个寄存器
两个读端口,读采用组合逻辑
一个写端口,写采用时序逻辑
就这样简单。
一个值得注意的是reg_we_i,写使能信号,容易被忽略
为什么不能没有使能信号?
因为,寄存器堆就无法判断当前周期是不是“真的要写寄存器”,从而可能发生误写和错误旁路。
代码:
`timescale 1ns / 1ps
`include "defines.v"
module regs(
input wire clk ,
input wire rst,
input wire [4:0] reg1_raddr_i ,
input wire [4:0] reg2_raddr_i ,
output wire [DW-1:0]reg1_rdata_o ,
output wire [DW-1:0]reg2_rdata_o ,
input wire reg_we_i ,
input wire [4:0] reg_waddr_i ,
input wire [DW-1:0] reg_wdata_i
);
reg [DW-1:0] REGS[0:31];
integer i;
always@(posedge clk)begin
if(rst == `RstEnable)begin
for(i=1;i<32;i=i+1)begin
REGS[i] <= `ZeroWord;
end
end
else if(reg_waddr_i != `ZeroReg && reg_we_i )begin
REGS[reg_waddr_i] <= reg_wdata_i;
end
end
assign reg1_rdata_o = (rst != `RstEnable)?(reg1_raddr_i == `ZeroReg)?`ZeroWord:(reg_we_i && reg1_raddr_i == reg_waddr_i)?reg_wdata_i:REGS[reg1_raddr_i]:`ZeroWord ;
assign reg2_rdata_o = (rst != `RstEnable)?(reg2_raddr_i == `ZeroReg)?`ZeroWord:(reg_we_i && reg2_raddr_i == reg_waddr_i)?reg_wdata_i:REGS[reg2_raddr_i]:`ZeroWord ;
endmodule
代码很短,从上到下可以分成三部分
一是实例化REGS数组
二是写逻辑,对应中间的always块
三是读逻辑,对应assign语句。
另一个值得关注的地方就是:
读逻辑中加了:判断读地址是0输出0
为什么读逻辑中要加判断读地址是0输出0?也就是代码为什么不是:
assign reg1_rdata_o = (rst != `RstEnable)?(reg_we_i && reg1_raddr_i == reg_waddr_i)?reg_wdata_i:REGS[reg1_raddr_i]:`ZeroWord ;
两种写法的区别在于,
采用的写法是强制0号寄存器输出0;
而上面给出的代码是要去读REGS[0]里边的内容
区别就在这里,万一0号寄存器中不是0,就出错了。
所以,采用强制输出是正确的。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/wangweiwei2020/article/details/162703478



