ctrl
module ctrl(
input wire [31:0]jump_addr_i,
input wire jump_en_i,
input wire hold_flag_ex_i,
output reg [31:0]jump_addr_o,
output reg jump_en_o,
output reg hold_flag_o
);
always @(*)begin
jump_addr_o = jump_addr_i;
jump_en_o = jump_en_i;
if( jump_en_i || hold_flag_ex_i)begin
hold_flag_o = 1'b1;
end
else begin
hold_flag_o = 1'b0;
end
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 hold_flag_i,
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 || hold_flag_i == 1'b1)
data_o <= set_data;
else
data_o <= data_i;
end
endmodule
ex
`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,
input wire[31:0] base_addr_i,
input wire[31:0] addr_offset_i,
//to regs
output reg[4:0] rd_addr_o,
output reg[31:0]rd_data_o,
output reg rd_wen_o,
//to ctrl
output reg[31:0]jump_addr_o,
output reg jump_en_o,
output reg hold_flag_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;
wire[4:0] shamt;
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];
assign shamt = inst_i[24:20];
// branch
//wire[31:0] jump_imm = {{19{inst_i[31]}},inst_i[31],inst_i[7],inst_i[30:25],inst_i[11:8],1'b0}; //改 21+6+4+1
wire op1_i_equal_op2_i;
wire op1_i_less_op2_i_signed;
wire op1_i_less_op2_i_unsigned;
assign op1_i_less_op2_i_signed = ($signed(op1_i) < $signed(op2_i))?1'b1:1'b0;
assign op1_i_less_op2_i_unsigned = (op1_i < op2_i)?1'b1:1'b0;
assign op1_i_equal_op2_i = (op1_i == op2_i)?1'b1:1'b0;
//ALU
wire[31:0] op1_i_add_op2_i;
wire[31:0] op1_i_and_op2_i;
wire[31:0] op1_i_xor_op2_i;
wire[31:0] op1_i_or_op2_i;
wire[31:0] op1_i_shift_letf_op2_i;
wire[31:0] op1_i_shift_right_op2_i;
wire[31:0] base_addr_add_addr_offset;
assign op1_i_add_op2_i = op1_i + op2_i; // 加法器
assign op1_i_and_op2_i = op1_i & op2_i; // 与
assign op1_i_xor_op2_i = op1_i ^ op2_i; // 异或
assign op1_i_or_op2_i = op1_i | op2_i; // 或
assign op1_i_shift_letf_op2_i = op1_i << op2_i; // 左移
assign op1_i_shift_right_op2_i = op1_i >> op2_i; // 右移
assign base_addr_add_addr_offset = base_addr_i + addr_offset_i; // 计算地址单元
// tpye I
wire[31:0] SRA_mask;
assign SRA_mask = (32'hffff_ffff) >> op2_i[4:0];
always @(*)begin
case(opcode)
`INST_TYPE_I:begin
jump_addr_o = 32'b0;
jump_en_o = 1'b0;
hold_flag_o = 1'b0;
case(func3)
`INST_ADDI:begin
rd_data_o = op1_i_add_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_SLTI:begin
rd_data_o = {31'b0,op1_i_less_op2_i_signed};
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_SLTIU:begin
rd_data_o = {31'b0,op1_i_less_op2_i_unsigned};
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_XORI:begin
rd_data_o = op1_i_xor_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_ORI:begin
rd_data_o = op1_i_or_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_ANDI:begin
rd_data_o = op1_i_add_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_SLLI:begin
rd_data_o = op1_i_shift_letf_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_SRI:begin
if(func7[5] == 1'b1) begin //SRAI
rd_data_o = ((op1_i_shift_right_op2_i) & SRA_mask) | ({32{op1_i[31]}} & (~SRA_mask));
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
else begin //SRLI
rd_data_o = op1_i_shift_right_op2_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
`INST_TYPE_R_M:begin
jump_addr_o = 32'b0;
jump_en_o = 1'b0;
hold_flag_o = 1'b0;
case(func3)
`INST_ADD_SUB:begin
if(func7[5] == 1'b0)begin//add
rd_data_o = op1_i_add_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
else begin
rd_data_o = op1_i - op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
end
`INST_SLL:begin
rd_data_o = op1_i_shift_letf_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_SLT:begin
rd_data_o = {31'b0,op1_i_less_op2_i_signed};
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_SLTU:begin
rd_data_o = {31'b0,op1_i_less_op2_i_unsigned};
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_XOR:begin
rd_data_o = op1_i_xor_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_OR:begin
rd_data_o = op1_i_or_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_AND:begin
rd_data_o = op1_i_and_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_SR:begin
if(func7[5] == 1'b1) begin //SRA
rd_data_o = ((op1_i_shift_right_op2_i) & SRA_mask) | ({32{op1_i[31]}} & (~SRA_mask));
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
else begin //SRL
rd_data_o = op1_i_shift_right_op2_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
`INST_TYPE_B:begin
rd_data_o = 32'b0;
rd_addr_o = 5'b0;
rd_wen_o = 1'b0;
case(func3)
`INST_BEQ:begin
jump_addr_o = base_addr_add_addr_offset ;
jump_en_o = op1_i_equal_op2_i;
hold_flag_o = 1'b0;
end
`INST_BNE:begin
jump_addr_o = base_addr_add_addr_offset;
jump_en_o = ~op1_i_equal_op2_i;
hold_flag_o = 1'b0;
end
`INST_BLT:begin
jump_addr_o = base_addr_add_addr_offset;
jump_en_o = op1_i_less_op2_i_signed;
hold_flag_o = 1'b0;
end
`INST_BGE:begin
jump_addr_o = base_addr_add_addr_offset;
jump_en_o = ~op1_i_less_op2_i_signed;
hold_flag_o = 1'b0;
end
`INST_BLTU:begin
jump_addr_o = base_addr_add_addr_offset;
jump_en_o = op1_i_less_op2_i_unsigned;
hold_flag_o = 1'b0;
end
`INST_BGEU:begin
jump_addr_o = base_addr_add_addr_offset;
jump_en_o = ~op1_i_less_op2_i_unsigned;
hold_flag_o = 1'b0;
end
default:begin
jump_addr_o = 32'b0;
jump_en_o = 1'b0;
hold_flag_o = 1'b0;
end
endcase
end
`INST_JAL:begin
rd_data_o = op1_i_add_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
jump_addr_o = base_addr_add_addr_offset;
jump_en_o = 1'b1;
hold_flag_o = 1'b0;
end
`INST_JALR:begin
rd_data_o = op1_i_add_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
jump_addr_o = base_addr_add_addr_offset;
jump_en_o = 1'b1;
hold_flag_o = 1'b0;
end
`INST_LUI:begin
rd_data_o = op1_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
jump_addr_o = 32'b0;
jump_en_o = 1'b0;
hold_flag_o = 1'b0;
end
`INST_AUIPC:begin
rd_data_o = op1_i_add_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
jump_addr_o = 32'b0;
jump_en_o = 1'b0;
hold_flag_o = 1'b0;
end
default:begin
rd_data_o = 32'b0;
rd_addr_o = 5'b0;
rd_wen_o = 1'b0;
jump_addr_o = 32'b0;
jump_en_o = 1'b0;
hold_flag_o = 1'b0;
end
endcase
end
endmodule
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 ,
output reg[31:0] base_addr_o ,
output reg[31:0] addr_offset_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;
wire[4:0] shamt;
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];
assign shamt = inst_i[24:20];
always @(*)begin
inst_o = inst_i;
inst_addr_o = inst_addr_i;
case(opcode)
`INST_TYPE_I:begin
base_addr_o = 32'b0;
addr_offset_o = 32'b0;
case(func3)
`INST_ADDI,`INST_SLTI,`INST_SLTIU,`INST_XORI,`INST_ORI,`INST_ANDI: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
`INST_SLLI,`INST_SRI:begin
rs1_addr_o = rs1;
rs2_addr_o = 5'b0;
op1_o = rs1_data_i;
op2_o = {27'b0,shamt};
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
base_addr_o = 32'b0;
addr_offset_o = 32'b0;
case(func3)
`INST_ADD_SUB,`INST_SLT,`INST_SLTU,`INST_XOR,`INST_OR,`INST_AND: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
`INST_SLL,`INST_SR:begin
rs1_addr_o = rs1;
rs2_addr_o = rs2;
op1_o = rs1_data_i;
op2_o = {27'b0,rs2_data_i[4:0]};
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_B:begin
case(func3)
`INST_BNE,`INST_BEQ,`INST_BLT,`INST_BGE,`INST_BLTU,`INST_BGEU:begin
rs1_addr_o = rs1;
rs2_addr_o = rs2;
op1_o = rs1_data_i;
op2_o = rs2_data_i;
rd_addr_o = 5'b0;
reg_wen = 1'b0;
base_addr_o = inst_addr_i;
addr_offset_o = {{19{inst_i[31]}},inst_i[31],inst_i[7],inst_i[30:25],inst_i[11:8],1'b0};
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;
base_addr_o = 32'b0;
addr_offset_o = 32'b0;
end
endcase
end
`INST_JAL:begin
rs1_addr_o = 5'b0;
rs2_addr_o = 5'b0;
op1_o = inst_addr_i;
op2_o = 32'h4;
rd_addr_o = rd;
reg_wen = 1'b1;
base_addr_o = inst_addr_i;
addr_offset_o = {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0};
end
`INST_LUI:begin
rs1_addr_o = 5'b0;
rs2_addr_o = 5'b0;
op1_o = {inst_i[31:12],12'b0};
op2_o = 32'b0;
rd_addr_o = rd;
reg_wen = 1'b1;
base_addr_o = 32'b0;
addr_offset_o = 32'b0;
end
`INST_JALR:begin
rs1_addr_o = rs1;
rs2_addr_o = 5'b0;
op1_o = inst_addr_i;
op2_o = 32'h4;
rd_addr_o = rd;
reg_wen = 1'b1;
base_addr_o = rs1_data_i;
addr_offset_o = {{20{imm[11]}},imm};
end
`INST_AUIPC:begin
rs1_addr_o = 5'b0;
rs2_addr_o = 5'b0;
op1_o = {inst_i[31:12],12'b0};
op2_o = inst_addr_i;
rd_addr_o = rd;
reg_wen = 1'b1;
base_addr_o = 32'b0;
addr_offset_o = 32'b0;
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;
base_addr_o = 32'b0;
addr_offset_o = 32'b0;
end
endcase
end
endmodule
id_ex
`include "defines.v"
module id_ex(
input wire clk ,
input wire rst ,
//from ctrl
input wire hold_flag_i ,
//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 ,
input wire[31:0] base_addr_i ,
input wire[31:0] addr_offset_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 ,
output wire[31:0] base_addr_o ,
output wire[31:0] addr_offset_o
);
dff_set #(32) dff1(clk,rst,hold_flag_i,`INST_NOP,inst_i,inst_o);
dff_set #(32) dff2(clk,rst,hold_flag_i,32'b0,inst_addr_i,inst_addr_o);
dff_set #(32) dff3(clk,rst,hold_flag_i,32'b0,op1_i,op1_o);
dff_set #(32) dff4(clk,rst,hold_flag_i,32'b0,op2_i,op2_o);
dff_set #(5) dff5(clk,rst,hold_flag_i,5'b0,rd_addr_i,rd_addr_o);
dff_set #(1) dff6(clk,rst,hold_flag_i,1'b0,reg_wen_i,reg_wen_o);
dff_set #(32) dff7(clk,rst,hold_flag_i,32'b0,base_addr_i,base_addr_o);
dff_set #(32) dff8(clk,rst,hold_flag_i,32'b0,addr_offset_i,addr_offset_o);
endmodule
if_id
`include "defines.v"
module if_id(
input wire clk,
input wire rst,
input wire hold_flag_i,
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,hold_flag_i,`INST_NOP,inst_i,inst_o);
dff_set #(32) dff2(clk,rst,hold_flag_i,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_v
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;
wire[31:0] id_base_addr_o;
wire[31:0] id_addr_offset_o;
//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;
wire[31:0] id_ex_base_addr_o;
wire[31:0] id_ex_addr_offset_o;
//ex to ctrl
wire[31:0] ex_jump_addr_o;
wire ex_jump_en_o;
wire ex_hold_flag_o;
//ctrl to pc_reg
wire[31:0] ctrl_jump_addr_o;
wire ctrl_jump_en_o;
//ctrl to if_id id_ex
wire ctrl_hold_flag_o;
pc_reg pc_reg_inst(
.clk (clk),
.rst (rst),
.jump_addr_i (ctrl_jump_addr_o), //&
.jump_en (ctrl_jump_en_o),
.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 ),
.hold_flag_i (ctrl_hold_flag_o ),
.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 ),
.base_addr_o (id_base_addr_o ),
.addr_offset_o (id_addr_offset_o )
);
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 ),
.hold_flag_i (ctrl_hold_flag_o ),
.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 ),
.base_addr_i (id_base_addr_o ),
.addr_offset_i (id_addr_offset_o ),
.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 ),
.base_addr_o (id_ex_base_addr_o ),
.addr_offset_o (id_ex_addr_offset_o )
);
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 ),
.base_addr_i (id_ex_base_addr_o ),
.addr_offset_i (id_ex_addr_offset_o ),
.rd_addr_o (ex_rd_addr_o ),
.rd_data_o (ex_rd_data_o ),
.rd_wen_o (ex_reg_wen_o ),
.jump_addr_o (ex_jump_addr_o ),
.jump_en_o (ex_jump_en_o ),
.hold_flag_o (ex_hold_flag_o )
);
ctrl ctrl_inst(
.jump_addr_i (ex_jump_addr_o),
.jump_en_i (ex_jump_en_o),
.hold_flag_ex_i (ex_hold_flag_o),
.jump_addr_o (ctrl_jump_addr_o),
.jump_en_o (ctrl_jump_en_o),
.hold_flag_o (ctrl_hold_flag_o)
);
endmodule
pc_reg
module pc_reg(
input wire clk,
input wire rst,
input wire[31:0] jump_addr_i,
input wire jump_en,
output reg[31:0] pc_o
);
always @(posedge clk) begin
if(rst == 1'b0)
pc_o <= 32'b0;
else if(jump_en)
pc_o <= jump_addr_i;
else
pc_o <= pc_o + 3'd4;
end
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