defines
// I type inst
`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
id
`include "defines.v"
module id(
//from if_id
input wire[31:0] inst_i,
input wire[31:0] inst_addr_i,
// to regs
output reg[4:0] rs1_addr_o,
output reg[4:0] rs2_addr_o,
// from regs
input wire[31:0] rs1_data_i,
input wire[31:0] rs2_data_i,
//to id_ex
output reg[31:0] inst_o,
output reg[31:0] inst_addr_o,
output reg[31:0] op1_o,
output reg[31:0] op2_o,
output reg[4:0] rd_addr_o,
output reg reg_wen
);
wire[6:0] opcode;
wire[4:0] rd;
wire[2:0] func3;
wire[4:0] rs1;
wire[4:0] rs2;
wire[6:0] func7;
wire[11:0]imm;
assign opcode = inst_i[6:0];
assign rd = inst_i[11:7];
assign func3 = inst_i[14:12];
assign rs1 = inst_i[19:15];
assign rs2 = inst_i[24:20];
assign func7 = inst_i[31:25];
assign imm = inst_i[31:20];
always @(*)begin
inst_o = inst_i;
inst_addr_o = inst_addr_i; //写反了
case(opcode)
`INST_TYPE_I:begin
case(func3)
`INST_ADDI:begin
rs1_addr_o = rs1;
rs2_addr_o = 5'b0;
op1_o = rs1_data_i;
op2_o = {{20{imm[11]}},imm};
rd_addr_o = rd;
reg_wen = 1'b1;
end
default:begin
rs1_addr_o = 5'b0;
rs2_addr_o = 5'b0;
op1_o = 32'b0;
op2_o = 32'b0;
rd_addr_o = 5'b0;
reg_wen = 1'b0;
end
endcase
end
`INST_TYPE_R_M:begin
case(func3)
`INST_ADD_SUB:begin
rs1_addr_o = rs1;
rs2_addr_o = rs2;
op1_o = rs1_data_i;
op2_o = rs2_data_i;
rd_addr_o = rd;
reg_wen = 1'b1;
end
default:begin
rs1_addr_o = 5'b0;
rs2_addr_o = 5'b0;
op1_o = 32'b0;
op2_o = 32'b0;
rd_addr_o = 5'b0;
reg_wen = 1'b0;
end
endcase
end
default:begin
rs1_addr_o = 5'b0;
rs2_addr_o = 5'b0;
op1_o = 32'b0;
op2_o = 32'b0;
rd_addr_o = 5'b0;
reg_wen = 1'b0;
end
endcase
end
endmodule
pc_reg
module pc_reg(
input wire clk,
input wire rst,
output reg[31:0] pc_o
);
always @(posedge clk) begin
if(rst == 1'b0)
pc_o <=32'b0;
else
pc_o <= pc_o + 3'd4;
end
endmodule
id_ex
`include "defines.v"
module id_ex(
input wire clk,
input wire rst,
//from id
input wire[31:0] inst_i,
input wire[31:0] inst_addr_i,
input wire[31:0] op1_i,
input wire[31:0] op2_i,
input wire[4:0] rd_addr_i,
input wire reg_wen_i,
//to ex
output wire[31:0] inst_o,
output wire[31:0] inst_addr_o,
output wire[31:0] op1_o,
output wire[31:0] op2_o,
output wire[4:0] rd_addr_o,
output wire reg_wen_o
);
dff_set #(32) dff1(clk,rst,`INST_NOP,inst_i,inst_o);
dff_set #(32) dff2(clk,rst,32'b0,inst_addr_i,inst_addr_o);
dff_set #(32) dff3(clk,rst,32'b0,op1_i,op1_o);
dff_set #(32) dff4(clk,rst,32'b0,op2_i,op2_o);
dff_set #(5) dff5(clk,rst,5'b0,rd_addr_i,rd_addr_o);
dff_set #(1) dff6(clk,rst,1'b0,reg_wen_i,reg_wen_o);
endmodule
if-id
`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,
output wire[31:0] inst_addr_o,
output wire[31:0] inst_o
);
dff_set #(32) dff1(clk,rst,`INST_NOP,inst_i,inst_o);
dff_set #(32) dff2(clk,rst,32'b0,inst_addr_i,inst_addr_o);
endmodule
if
module ifetch(
//from pc
input wire[31:0] pc_addr_i,
//from rom
input wire[31:0] rom_inst_i,
//to 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;
assign inst_addr_o = pc_addr_i;
assign inst_o = rom_inst_i;
endmodule
open_risc
module open_risc_v(
input wire clk ,
input wire rst ,
input wire [31:0] inst_i ,
output wire [31:0] inst_addr_o
);
//pc to if
wire[31:0] pc_reg_pc_o;
//if to if_id
wire[31:0] if_inst_addr_o;
wire[31:0] if_inst_o;
// if_id to id
wire[31:0] if_id_inst_addr_o;
wire[31:0] if_id_inst_o;
//ex to regs
wire[4:0] ex_rd_addr_o;
wire[31:0] ex_rd_data_o;
wire ex_reg_wen_o;
//id to regs
wire[4:0] id_rs1_addr_o;
wire[4:0] id_rs2_addr_o;
//id to id_ex
wire[31:0] id_inst_o;
wire[31:0] id_inst_addr_o;
wire[31:0] id_op1_o;
wire[31:0] id_op2_o;
wire[4:0] id_rd_addr_o;
wire id_reg_wen;
//regs to id
wire[31:0] regs_reg1_rdata_o;
wire[31:0] regs_reg2_rdata_o;
//id_ex to ex
wire[31:0] id_ex_inst_o;
wire[31:0] id_ex_inst_addr_o;
wire[31:0] id_ex_op1_o;
wire[31:0] id_ex_op2_o;
wire[4:0] id_ex_rd_addr_o;
wire id_ex_reg_wen;
pc_reg pc_reg_inst(
.clk (clk),
.rst (rst),
.pc_o (pc_reg_pc_o)
);
ifetch ifetch_inst(
.pc_addr_i (pc_reg_pc_o),
.rom_inst_i (inst_i),
.if2rom_addr_o (inst_addr_o),
.inst_addr_o (if_inst_addr_o),
.inst_o (if_inst_o)
);
if_id if_id_inst(
.clk (clk ),
.rst (rst ),
.inst_i (if_inst_o ),
.inst_addr_i (if_inst_addr_o ),
.inst_addr_o (if_id_inst_addr_o),
.inst_o (if_id_inst_o )
);
id id_inst(
.inst_i (if_id_inst_o),
.inst_addr_i (if_id_inst_addr_o),
.rs1_addr_o (id_rs1_addr_o),
.rs2_addr_o (id_rs2_addr_o),
.rs1_data_i (regs_reg1_rdata_o),
.rs2_data_i (regs_reg2_rdata_o),
.inst_o (id_inst_o),
.inst_addr_o (id_inst_addr_o),
.op1_o (id_op1_o),
.op2_o (id_op2_o),
.rd_addr_o (id_rd_addr_o),
.reg_wen (id_reg_wen)
);
regs regs_inst(
.clk (clk),
.rst (rst),
.reg1_raddr_i (id_rs1_addr_o),
.reg2_raddr_i (id_rs2_addr_o),
.reg1_rdata_o (regs_reg1_rdata_o),
.reg2_rdata_o (regs_reg2_rdata_o),
.reg_waddr_i (ex_rd_addr_o),
.reg_wdata_i (ex_rd_data_o),
.reg_wen (ex_reg_wen_o)
);
id_ex id_ex_inst(
.clk (clk),
.rst (rst),
.inst_i (id_inst_o),
.inst_addr_i (id_inst_addr_o),
.op1_i (id_op1_o),
.op2_i (id_op2_o),
.rd_addr_i (id_rd_addr_o),
.reg_wen_i (id_reg_wen),
.inst_o (id_ex_inst_o),
.inst_addr_o (id_ex_inst_addr_o),
.op1_o (id_ex_op1_o),
.op2_o (id_ex_op2_o),
.rd_addr_o (id_ex_rd_addr_o),
.reg_wen_o (id_ex_reg_wen)
);
ex ex_inst(
.inst_i (id_ex_inst_o),
.inst_addr_i (id_ex_inst_addr_o),
.op1_i (id_ex_op1_o),
.op2_i (id_ex_op2_o),
.rd_addr_i (id_ex_rd_addr_o),
.rd_wen_i (id_ex_reg_wen),
.rd_addr_o (ex_rd_addr_o),
.rd_data_o (ex_rd_data_o),
.rd_wen_o (ex_reg_wen_o)
);
endmodule
regs
module regs(
input wire clk,
input wire rst,
//from id
input wire[4:0] reg1_raddr_i,
input wire[4:0] reg2_raddr_i,
//to id
output reg[31:0] reg1_rdata_o,
output reg[31:0] reg2_rdata_o,
//from ex
input wire[4:0] reg_waddr_i,
input wire[31:0]reg_wdata_i,
input reg_wen
);
reg[31:0] regs[0:31];
integer i;
always @(*)begin
if(rst == 1'b0)
reg1_rdata_o <= 32'b0;
else if(reg1_raddr_i == 5'b0)
reg1_rdata_o <= 32'b0;
else if(reg_wen && reg1_raddr_i == reg_waddr_i)
reg1_rdata_o <= reg_wdata_i;
else
reg1_rdata_o <= regs[reg1_raddr_i];
end
always @(*)begin
if(rst == 1'b0)
reg2_rdata_o <= 32'b0;
else if(reg2_raddr_i == 5'b0)
reg2_rdata_o <= 32'b0;
else if(reg_wen && reg2_raddr_i == reg_waddr_i)
reg2_rdata_o <= reg_wdata_i;
else
reg2_rdata_o <= regs[reg2_raddr_i];
end
always @(posedge clk)begin
if(rst == 1'b0) begin
for(i=0;i<31;i=i+1)begin
regs[i] <= 32'b0;
end
end
else if(reg_wen && reg_waddr_i != 5'b0)begin
regs[reg_waddr_i] <= reg_wdata_i;
end
end
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
inst_o = rom_mem[inst_addr_i>>2];
end
endmodule
defines
// I type inst
`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
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;
end
endmodule
ex.v
`include "defines.v"
module ex(
//from id_ex
input wire[31:0] inst_i,
input wire[31:0] inst_addr_i,
input wire[31:0] op1_i,
input wire[31:0] op2_i,
input wire[4:0] rd_addr_i,
input wire rd_wen_i,
//to regs
output reg[4:0] rd_addr_o,
output reg[31:0]rd_data_o,
output reg rd_wen_o
);
wire[6:0] opcode;
wire[4:0] rd;
wire[2:0] func3;
wire[4:0] rs1;
wire[4:0] rs2;
wire[6:0] func7;
wire[11:0]imm;
assign opcode = inst_i[6:0];
assign rd = inst_i[11:7];
assign func3 = inst_i[14:12];
assign rs1 = inst_i[19:15];
assign rs2 = inst_i[24:20];
assign func7 = inst_i[31:25];
assign imm = inst_i[31:20];
always @(*)begin
case(opcode)
`INST_TYPE_I:begin
case(func3)
`INST_ADDI:begin
rd_data_o = op1_i + op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
default:begin
rd_data_o = 32'b0;
rd_addr_o = 5'b0;
rd_wen_o = 1'b0;
end
endcase
end
`INST_TYPE_R_M:begin
case(func3)
`INST_ADD_SUB:begin
if(func7 == 7'b000_0000)begin//add
rd_data_o = op1_i + op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
else begin
rd_data_o = op2_i - op1_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
end
default:begin
rd_data_o = 32'b0;
rd_addr_o = 5'b0;
rd_wen_o = 1'b0;
end
endcase
end
default:begin
rd_data_o = 32'b0;
rd_addr_o = 5'b0;
rd_wen_o = 1'b0;
end
endcase
end
endmodule