寄存器组32位,x0恒为32'b0。为只读。
ADDI为加立即数
I型指令,imm为12位要进行符号位扩展。
最高位为符号位,最高位为1其他位扩展为1,最高位为0,其余位扩展为0.
I型指令流可以实现NOP指令,空跑。 实现的就是把0加上x0放到x0上,因为x0永远为0,所以对此操作无效。
risc-v中没有mov指令,通过立即数加ADDI实现,ADDI x5,x4,0
- 在I型指令中,addi指令是需要进行符号位扩展,但是andi、ori、xori指令只需要进行零扩展即可
R型指令: 两个操作数都为寄存器
实现 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