Risc-v架构简易CPU实现(不包括ROM,RAM)
之前看到很多人都用mips架构写了cpu(挺常见的计组大作业),所以我跟着学完以后照猫画虎写了riscv的。屑作,不足请斧正。
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
module ifetch( //从pc来的地址 input wire[31:0] pc_addr_i, //指令,从rom input wire[31:0] rom_inst_i, //to rom output wire[31:0] to_rom_addr_o, //查找完,该译码了 output wire[31:0] inst_addr_o, output wire[31:0] inst_o ); assign to_rom_addr_o = pc_addr_i; assign inst_addr_o = pc_addr_i; assign inst_o = rom_inst_i; endmodule
`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
`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
`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
`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];
// tpye 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_left_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_left_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];
//wire[31:0] store_offset_addr = {{20{inst_i[31]}},inst_i[31:25],inst_i[11:7]};
// tpye store && load index
wire[1:0] store_index = base_addr_add_addr_offset[1:0];
wire[1:0] load_index = base_addr_add_addr_offset[1:0];
always @(*)begin
case(opcode)
`INST_TYPE_I:begin
jump_addr_o = 32'b0;
jump_en_o = 1'b0;
hold_flag_o = 1'b0;
mem_wr_req_o = 1'b0;
mem_wr_sel_o = 4'b0;
mem_wr_addr_o = 32'b0;
mem_wr_data_o = 32'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 = {30'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 = {30'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_and_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_SLLI:begin
rd_data_o = op1_i_shift_left_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;
mem_wr_req_o = 1'b0;
mem_wr_sel_o = 4'b0;
mem_wr_addr_o = 32'b0;
mem_wr_data_o = 32'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_left_op2_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_SLT:begin
rd_data_o = {30'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 = {30'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;
mem_wr_req_o = 1'b0;
mem_wr_sel_o = 4'b0;
mem_wr_addr_o = 32'b0;
mem_wr_data_o = 32'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_TYPE_L:begin
jump_addr_o = 32'b0;
jump_en_o = 1'b0;
hold_flag_o = 1'b0;
mem_wr_req_o = 1'b0;
mem_wr_sel_o = 4'b0;
mem_wr_addr_o = 32'b0;
mem_wr_data_o = 32'b0;
case(func3)
`INST_LW:begin
rd_data_o = mem_rd_data_i;
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
end
`INST_LH:begin
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
case(load_index[1])
1'b0:begin
rd_data_o = {{16{mem_rd_data_i[15]}},mem_rd_data_i[15:0]};
end
1'b1:begin
rd_data_o = {{16{mem_rd_data_i[31]}},mem_rd_data_i[31:16]};
end
default:begin
rd_data_o = 32'b0;
end
endcase
end
`INST_LB:begin
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
case(load_index)
2'b00:begin
rd_data_o = {{24{mem_rd_data_i[7]}},mem_rd_data_i[7:0]};
end
2'b01:begin
rd_data_o = {{24{mem_rd_data_i[15]}},mem_rd_data_i[15:8]};
end
2'b10:begin
rd_data_o = {{24{mem_rd_data_i[23]}},mem_rd_data_i[23:16]};
end
2'b11:begin
rd_data_o = {{24{mem_rd_data_i[31]}},mem_rd_data_i[31:24]};
end
default:begin
rd_data_o = 32'b0;
end
endcase
end
`INST_LHU:begin
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
case(load_index[1]) //二字节对齐 所以是第 1 位,第零位默认为0的,其实这里要做处理,
1'b0:begin //如果发现最低为不为零要进行硬件报异常(说明你程序员的代码没有二字节对齐,16位对齐)
rd_data_o = {16'b0,mem_rd_data_i[15:0]};
end
1'b1:begin
rd_data_o = {16'b0,mem_rd_data_i[31:16]};
end
default:begin
rd_data_o = 32'b0;
end
endcase
end
`INST_LBU:begin
rd_addr_o = rd_addr_i;
rd_wen_o = 1'b1;
case(load_index)
2'b00:begin
rd_data_o = {24'b0,mem_rd_data_i[7:0]};
end
2'b01:begin
rd_data_o = {24'b0,mem_rd_data_i[15:8]};
end
2'b10:begin
rd_data_o = {24'b0,mem_rd_data_i[23:16]};
end
2'b11:begin
rd_data_o = {24'b0,mem_rd_data_i[31:24]};
end
default:begin
rd_data_o = 32'b0;
end
endcase
end
default:begin
rd_data_o = 32'b0;
rd_addr_o = 5'b0;
rd_wen_o = 1'b0;
end
endcase
end
`INST_TYPE_S:begin
jump_addr_o = 32'b0;
jump_en_o = 1'b0;
hold_flag_o = 1'b0;
rd_data_o = 32'b0;
rd_addr_o = 5'b0;
rd_wen_o = 1'b0;
case(func3)
`INST_SW:begin
mem_wr_req_o = 1'b1;
mem_wr_sel_o = 4'b1111;
mem_wr_addr_o = base_addr_add_addr_offset;
mem_wr_data_o = op2_i;
end
`INST_SH:begin
mem_wr_req_o = 1'b1;
mem_wr_addr_o = base_addr_add_addr_offset;
case(store_index)
1'b0:begin
mem_wr_data_o = {16'b0,op2_i[15:0]};
mem_wr_sel_o = 4'b0011;
end
1'b1:begin
mem_wr_data_o = {op2_i[15:0],16'b0};
mem_wr_sel_o = 4'b1100;
end
default:begin
mem_wr_data_o = 32'b0;
mem_wr_sel_o = 4'b0000;
end
endcase
end
`INST_SB:begin
mem_wr_req_o = 1'b1;
mem_wr_addr_o = base_addr_add_addr_offset;
case(store_index)
2'b00:begin
mem_wr_data_o = {24'b0,op2_i[7:0]};
mem_wr_sel_o = 4'b0001;
end
2'b01:begin
mem_wr_data_o = {16'b0,op2_i[7:0],8'b0};
mem_wr_sel_o = 4'b0010;
end
2'b10:begin
mem_wr_data_o = {8'b0,op2_i[7:0],16'b0};
mem_wr_sel_o = 4'b0100;
end
2'b11:begin
mem_wr_data_o = {op2_i[7:0],24'b0};
mem_wr_sel_o = 4'b1000;
end
default:begin
mem_wr_data_o = 32'b0;
mem_wr_sel_o = 4'b0000;
end
endcase
end
default:begin
mem_wr_req_o = 1'b0;
mem_wr_sel_o = 4'b0;
mem_wr_addr_o = 32'b0;
mem_wr_data_o = 32'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;
mem_wr_req_o = 1'b0;
mem_wr_sel_o = 4'b0;
mem_wr_addr_o = 32'b0;
mem_wr_data_o = 32'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;
mem_wr_req_o = 1'b0;
mem_wr_sel_o = 4'b0;
mem_wr_addr_o = 32'b0;
mem_wr_data_o = 32'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;
mem_wr_req_o = 1'b0;
mem_wr_sel_o = 4'b0;
mem_wr_addr_o = 32'b0;
mem_wr_data_o = 32'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;
mem_wr_req_o = 1'b0;
mem_wr_sel_o = 4'b0;
mem_wr_addr_o = 32'b0;
mem_wr_data_o = 32'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;
mem_wr_req_o = 1'b0;
mem_wr_sel_o = 4'b0;
mem_wr_addr_o = 32'b0;
mem_wr_data_o = 32'b0;
end
endcase
end
endmodule
module open_cpu( 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
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
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