关注

从零开始设计riscv cpu记录之三

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

文章来源crawl

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--