tinyriscv - pc_reg模块 if取指模块 ROM

172 阅读3分钟

寄存器组32位,x0恒为32'b0。为只读。

image.png ADDI为加立即数

I型指令,imm为12位要进行符号位扩展。

最高位为符号位,最高位为1其他位扩展为1,最高位为0,其余位扩展为0.

I型指令流可以实现NOP指令,空跑。 实现的就是把0加上x0放到x0上,因为x0永远为0,所以对此操作无效。

risc-v中没有mov指令,通过立即数加ADDI实现,ADDI x5,x4,0 image.png

image.png

  • 在I型指令中,addi指令是需要进行符号位扩展,但是andi、ori、xori指令只需要进行零扩展即可

R型指令: 两个操作数都为寄存器

image.png

image.png

实现 pc_reg 模块


module pc_reg(
input wire clk,
input wire rst,
output reg [31:0]pc_o);
    
    always@(posedge clk) begin
        if(rst == 1'b1)
            pc_o <= 32'b0;
        else
            //rom中 四个内存放一个地址,加四取下一条指令
            pc_o <= pc_o + 3'd4;

    end







endmodule

取指模块

module ifetch(
//来自pc
input wire [31:0] pc_addr_i,
//来自rom
input wire [31:0] rom_inst_i,
//to rom   指令地址地址给rom

output wire [31:0] if2rom_addr_o,
// to if_id
output wire [31:0] inst_addr_o,
output wire [31:0] inst_o);


//
assign if2rom_addr_o = pc_addr_i;
// 指令地址的输出 来自pc
assign inst_addr_o = pc_addr_i;
//指令来自rom的输入
assign inst_o = rom_inst_i;







endmodule

ROM模块

module rom(
input wire [31:0] inst_addr_i,
output reg [31:0] inst_o);

    reg [31:0]rom_mem[0:4095] // 4096个32b 的空间

    always(*) begin
    
        // 因为输入的指令地址是加四的,而rom是加1.所以对地址缩小四倍 右移两位
        inst_o = rom_mem[inst_addr_i>>2] ;
    
    
    
    end

endmodule

if_id的输入为inst_addr_o,inst_o。

if_id模块

include可以使用这个语句进行文件包含,一般在被包含的文件里定义一些常用的task和define方便后续的使用

//包含进去
`include  "defines.v"
module if_id(
input wire clk,
input wire rst,
input wire [31:0] inst_i,
input wire [31:0] inst_addr_i,

ouput wire[31:0] inst_addr_o,
output wire [31:0]inst_o);



//always@(posedge clk)begin
//    if(rst == 1'b0)
//    // NOP指令。 32'b0000_0013  通过将宏定义该指令
//        inst_o <= `INST_NOP;
//    else
//        inst_o <= inst_i;
//end

//对指令和地址打一拍。 
dff_set #(32) dff1(clk,rst,`INST_NOP,inst_i,inst_o);

dff_set #(32) dff1(clk,rst,32'b0,inst_addr_i,inst_addr_o);

代码复用dff_set模块

module  dff_set #(parameter DW = 32)
(
	input wire clk,
	input wire rst,
	input wire [DW-1:0]  set_data, 
	input wire [DW-1:0]  data_i, 
	output reg [DW-1:0]  data_o	
);
always@(posedge clk) begin
    if(rst == 1'b0)
        data_o <= set_data;
    else
        data_o <= data_i;
    







defines.v

`define INST_TYPE_I 7'b0010011
`define INST_ADDI   3'b000
`define INST_SLTI   3'b010
`define INST_SLTIU  3'b011
`define INST_XORI   3'b100
`define INST_ORI    3'b110
`define INST_ANDI   3'b111
`define INST_SLLI   3'b001
`define INST_SRI    3'b101

// L type inst
`define INST_TYPE_L 7'b0000011
`define INST_LB     3'b000
`define INST_LH     3'b001
`define INST_LW     3'b010
`define INST_LBU    3'b100
`define INST_LHU    3'b101

// S type inst
`define INST_TYPE_S 7'b0100011
`define INST_SB     3'b000
`define INST_SH     3'b001
`define INST_SW     3'b010

// R and M type inst
`define INST_TYPE_R_M 7'b0110011
// R type inst
`define INST_ADD_SUB 3'b000
`define INST_SLL    3'b001
`define INST_SLT    3'b010
`define INST_SLTU   3'b011
`define INST_XOR    3'b100
`define INST_SR     3'b101
`define INST_OR     3'b110
`define INST_AND    3'b111
// M type inst
`define INST_MUL    3'b000
`define INST_MULH   3'b001
`define INST_MULHSU 3'b010
`define INST_MULHU  3'b011
`define INST_DIV    3'b100
`define INST_DIVU   3'b101
`define INST_REM    3'b110
`define INST_REMU   3'b111

// J type inst
`define INST_JAL    7'b1101111
`define INST_JALR   7'b1100111

`define INST_LUI    7'b0110111
`define INST_AUIPC  7'b0010111
`define INST_NOP    32'h00000013
`define INST_NOP_OP 7'b0000001
`define INST_MRET   32'h30200073
`define INST_RET    32'h00008067

`define INST_FENCE  7'b0001111
`define INST_ECALL  32'h73
`define INST_EBREAK 32'h00100073

// J type inst
`define INST_TYPE_B 7'b1100011
`define INST_BEQ    3'b000
`define INST_BNE    3'b001
`define INST_BLT    3'b100
`define INST_BGE    3'b101
`define INST_BLTU   3'b110
`define INST_BGEU   3'b111