[Add] la32r cpu framework add
This commit is contained in:
109
lacpu/rtl/cpu/alu.v
Executable file
109
lacpu/rtl/cpu/alu.v
Executable file
@@ -0,0 +1,109 @@
|
||||
module alu(
|
||||
input [11:0] alu_op ,
|
||||
input [31:0] alu_src1 ,
|
||||
input [31:0] alu_src2 ,
|
||||
output [31:0] alu_result ,
|
||||
|
||||
output Carry ,
|
||||
output Sign ,
|
||||
output Overflow ,
|
||||
output Zero
|
||||
);
|
||||
|
||||
wire op_add;
|
||||
wire op_sub;
|
||||
wire op_lui;
|
||||
wire op_slt;
|
||||
wire op_sltu;
|
||||
wire op_and;
|
||||
wire op_or;
|
||||
wire op_nor;
|
||||
wire op_xor;
|
||||
wire op_sll;
|
||||
wire op_srl;
|
||||
wire op_sra;
|
||||
|
||||
|
||||
assign op_add = alu_op[ 0];
|
||||
assign op_sub = alu_op[ 1];
|
||||
assign op_slt = alu_op[ 2];
|
||||
assign op_sltu = alu_op[ 3];
|
||||
assign op_and = alu_op[ 4];
|
||||
assign op_nor = alu_op[ 5];
|
||||
assign op_or = alu_op[ 6];
|
||||
assign op_xor = alu_op[ 7];
|
||||
assign op_sll = alu_op[ 8];
|
||||
assign op_srl = alu_op[ 9];
|
||||
assign op_sra = alu_op[10];
|
||||
assign op_lui = alu_op[11];
|
||||
|
||||
wire [31:0] add_sub_result;
|
||||
wire [31:0] slt_result;
|
||||
wire [31:0] sltu_result;
|
||||
wire [31:0] and_result;
|
||||
wire [31:0] nor_result;
|
||||
wire [31:0] or_result;
|
||||
wire [31:0] xor_result;
|
||||
wire [31:0] lui_result;
|
||||
wire [31:0] sll_result;
|
||||
wire [63:0] sr64_result;
|
||||
wire [31:0] sr_result;
|
||||
|
||||
// 32-bit adder
|
||||
wire [31:0] adder_a;
|
||||
wire [31:0] adder_b;
|
||||
wire adder_cin;
|
||||
wire [31:0] adder_result;
|
||||
wire adder_cout;
|
||||
|
||||
assign adder_a = alu_src1;
|
||||
assign adder_b = (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2;
|
||||
assign adder_cin = (op_sub | op_slt | op_sltu) ? 1'b1 : 1'b0;
|
||||
assign {adder_cout, adder_result} = adder_a + adder_b + adder_cin;
|
||||
|
||||
// ADD, SUB result
|
||||
assign add_sub_result = adder_result;
|
||||
|
||||
// SLT result
|
||||
assign slt_result[31:1] = 31'b0;
|
||||
assign slt_result[0] = (alu_src1[31] & ~alu_src2[31])
|
||||
| ((alu_src1[31] ~^ alu_src2[31]) & adder_result[31]);
|
||||
|
||||
// SLTU result
|
||||
assign sltu_result[31:1] = 31'b0;
|
||||
assign sltu_result[0] = ~adder_cout;
|
||||
|
||||
// bitwise operation
|
||||
assign and_result = alu_src1 & alu_src2;
|
||||
assign or_result = alu_src1 | alu_src2;
|
||||
assign nor_result = ~or_result;
|
||||
assign xor_result = alu_src1 ^ alu_src2;
|
||||
assign lui_result = {alu_src2[19:0], 12'b0};
|
||||
|
||||
// SLL result
|
||||
assign sll_result = alu_src1 << alu_src2[4:0];
|
||||
|
||||
// SRL, SRA result
|
||||
assign sr64_result = {{32{op_sra & alu_src1[31]}}, alu_src1[31:0]} >> alu_src2[4:0];
|
||||
|
||||
assign sr_result = sr64_result[31:0];
|
||||
|
||||
// final result mux
|
||||
assign alu_result = ({32{op_add|op_sub}} & add_sub_result)
|
||||
| ({32{op_slt }} & slt_result)
|
||||
| ({32{op_sltu }} & sltu_result)
|
||||
| ({32{op_and }} & and_result)
|
||||
| ({32{op_nor }} & nor_result)
|
||||
| ({32{op_or }} & or_result)
|
||||
| ({32{op_xor }} & xor_result)
|
||||
| ({32{op_lui }} & lui_result)
|
||||
| ({32{op_sll }} & sll_result)
|
||||
| ({32{op_srl|op_sra}} & sr_result);
|
||||
assign Carry = op_sub ^ adder_cout;
|
||||
assign Sign = alu_result[31];
|
||||
assign Overflow = (op_add|op_sub) ? ( adder_a[31] & adder_b[31] & adder_cout)
|
||||
| (~adder_a[31] & ~adder_b[31] & ~adder_cout)
|
||||
: 1'b0;
|
||||
assign Zero = (alu_result == 32'b0);
|
||||
|
||||
endmodule
|
||||
131
lacpu/rtl/cpu/cpu_top.v
Executable file
131
lacpu/rtl/cpu/cpu_top.v
Executable file
@@ -0,0 +1,131 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module mycpu_top(
|
||||
input clk,
|
||||
input resetn,
|
||||
// inst sram interface
|
||||
output inst_sram_en,
|
||||
output [ 3:0] inst_sram_wen,
|
||||
output [31:0] inst_sram_addr,
|
||||
output [31:0] inst_sram_wdata,
|
||||
input [31:0] inst_sram_rdata,
|
||||
// data sram interface
|
||||
output data_sram_en,
|
||||
output [ 3:0] data_sram_wen,
|
||||
output [31:0] data_sram_addr,
|
||||
output [31:0] data_sram_wdata,
|
||||
input [31:0] data_sram_rdata,
|
||||
// trace debug interface
|
||||
output [31:0] debug_wb_pc,
|
||||
output [ 3:0] debug_wb_rf_wen,
|
||||
output [ 4:0] debug_wb_rf_wnum,
|
||||
output [31:0] debug_wb_rf_wdata
|
||||
);
|
||||
reg reset;
|
||||
always @(posedge clk) reset <= ~resetn;
|
||||
|
||||
wire ds_allowin;
|
||||
wire es_allowin;
|
||||
wire ms_allowin;
|
||||
wire ws_allowin;
|
||||
wire fs_to_ds_valid;
|
||||
wire ds_to_es_valid;
|
||||
wire es_to_ms_valid;
|
||||
wire ms_to_ws_valid;
|
||||
wire [`FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus;
|
||||
wire [`DS_TO_ES_BUS_WD -1:0] ds_to_es_bus;
|
||||
wire [`ES_TO_MS_BUS_WD -1:0] es_to_ms_bus;
|
||||
wire [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus;
|
||||
wire [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus;
|
||||
wire [`BR_BUS_WD -1:0] br_bus;
|
||||
|
||||
// IF stage
|
||||
if_stage if_stage(
|
||||
.clk (clk ),
|
||||
.reset (reset ),
|
||||
//allowin
|
||||
.ds_allowin (ds_allowin ),
|
||||
//brbus
|
||||
.br_bus (br_bus ),
|
||||
//outputs
|
||||
.fs_to_ds_valid (fs_to_ds_valid ),
|
||||
.fs_to_ds_bus (fs_to_ds_bus ),
|
||||
// inst sram interface
|
||||
.inst_sram_en (inst_sram_en ),
|
||||
.inst_sram_wen (inst_sram_wen ),
|
||||
.inst_sram_addr (inst_sram_addr ),
|
||||
.inst_sram_wdata(inst_sram_wdata),
|
||||
.inst_sram_rdata(inst_sram_rdata)
|
||||
);
|
||||
// ID stage
|
||||
id_stage id_stage(
|
||||
.clk (clk ),
|
||||
.reset (reset ),
|
||||
//allowin
|
||||
.es_allowin (es_allowin ),
|
||||
.ds_allowin (ds_allowin ),
|
||||
//from fs
|
||||
.fs_to_ds_valid (fs_to_ds_valid ),
|
||||
.fs_to_ds_bus (fs_to_ds_bus ),
|
||||
//to es
|
||||
.ds_to_es_valid (ds_to_es_valid ),
|
||||
.ds_to_es_bus (ds_to_es_bus ),
|
||||
//to rf: for write back
|
||||
.ws_to_rf_bus (ws_to_rf_bus )
|
||||
);
|
||||
// EXE stage
|
||||
exe_stage exe_stage(
|
||||
.clk (clk ),
|
||||
.reset (reset ),
|
||||
//allowin
|
||||
.ms_allowin (ms_allowin ),
|
||||
.es_allowin (es_allowin ),
|
||||
//from ds
|
||||
.ds_to_es_valid (ds_to_es_valid ),
|
||||
.ds_to_es_bus (ds_to_es_bus ),
|
||||
//to ms
|
||||
.es_to_ms_valid (es_to_ms_valid ),
|
||||
.es_to_ms_bus (es_to_ms_bus ),
|
||||
//to fs
|
||||
.br_bus (br_bus ),
|
||||
// data sram interface
|
||||
.data_sram_en (data_sram_en ),
|
||||
.data_sram_wen (data_sram_wen ),
|
||||
.data_sram_addr (data_sram_addr ),
|
||||
.data_sram_wdata(data_sram_wdata)
|
||||
);
|
||||
// MEM stage
|
||||
mem_stage mem_stage(
|
||||
.clk (clk ),
|
||||
.reset (reset ),
|
||||
//allowin
|
||||
.ws_allowin (ws_allowin ),
|
||||
.ms_allowin (ms_allowin ),
|
||||
//from es
|
||||
.es_to_ms_valid (es_to_ms_valid ),
|
||||
.es_to_ms_bus (es_to_ms_bus ),
|
||||
//to ws
|
||||
.ms_to_ws_valid (ms_to_ws_valid ),
|
||||
.ms_to_ws_bus (ms_to_ws_bus ),
|
||||
//from data-sram
|
||||
.data_sram_rdata(data_sram_rdata)
|
||||
);
|
||||
// WB stage
|
||||
wb_stage wb_stage(
|
||||
.clk (clk ),
|
||||
.reset (reset ),
|
||||
//allowin
|
||||
.ws_allowin (ws_allowin ),
|
||||
//from ms
|
||||
.ms_to_ws_valid (ms_to_ws_valid ),
|
||||
.ms_to_ws_bus (ms_to_ws_bus ),
|
||||
//to rf: for write back
|
||||
.ws_to_rf_bus (ws_to_rf_bus ),
|
||||
//trace debug interface
|
||||
.debug_wb_pc (debug_wb_pc ),
|
||||
.debug_wb_rf_wen (debug_wb_rf_wen ),
|
||||
.debug_wb_rf_wnum (debug_wb_rf_wnum ),
|
||||
.debug_wb_rf_wdata(debug_wb_rf_wdata)
|
||||
);
|
||||
|
||||
endmodule
|
||||
147
lacpu/rtl/cpu/exe_stage.v
Executable file
147
lacpu/rtl/cpu/exe_stage.v
Executable file
@@ -0,0 +1,147 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module exe_stage(
|
||||
input clk ,
|
||||
input reset ,
|
||||
//allowin
|
||||
input ms_allowin ,
|
||||
output es_allowin ,
|
||||
//from ds
|
||||
input ds_to_es_valid,
|
||||
input [`DS_TO_ES_BUS_WD -1:0] ds_to_es_bus ,
|
||||
//to ms
|
||||
output es_to_ms_valid,
|
||||
output [`ES_TO_MS_BUS_WD -1:0] es_to_ms_bus ,
|
||||
//to fs
|
||||
output [`BR_BUS_WD -1:0] br_bus ,
|
||||
// data sram interface
|
||||
output data_sram_en ,
|
||||
output [ 3:0] data_sram_wen ,
|
||||
output [31:0] data_sram_addr ,
|
||||
output [31:0] data_sram_wdata
|
||||
);
|
||||
|
||||
reg es_valid ;
|
||||
wire es_ready_go ;
|
||||
|
||||
reg [`DS_TO_ES_BUS_WD -1:0] ds_to_es_bus_r;
|
||||
wire [11:0] es_alu_op;
|
||||
wire es_src1_is_pc;
|
||||
wire es_src2_is_imm;
|
||||
wire es_src2_is_4;
|
||||
wire es_mem_to_reg;
|
||||
wire es_reg_we;
|
||||
wire es_mem_we;
|
||||
wire [ 4:0] es_load_op;
|
||||
wire [ 2:0] es_store_op;
|
||||
wire [ 8:0] es_branch_op;
|
||||
wire [ 4:0] es_dest;
|
||||
wire [31:0] es_imm;
|
||||
wire [31:0] es_rf_rdata1;
|
||||
wire [31:0] es_rf_rdata2;
|
||||
wire [31:0] es_pc ;
|
||||
|
||||
|
||||
assign {es_alu_op , //158:147
|
||||
es_src1_is_pc , //146:146
|
||||
es_src2_is_imm , //145:145
|
||||
es_src2_is_4 , //144:144
|
||||
es_mem_to_reg , //143:143
|
||||
es_reg_we , //142:142
|
||||
es_mem_we , //141:141
|
||||
es_load_op , //140:136
|
||||
es_store_op , //135:133
|
||||
es_branch_op ,
|
||||
es_dest , //132:128
|
||||
es_imm , //127:96
|
||||
es_rf_rdata1 , //95 :64
|
||||
es_rf_rdata2 , //63 :32
|
||||
es_pc //31 :0
|
||||
} = ds_to_es_bus_r;
|
||||
|
||||
wire br_taken;
|
||||
wire [31:0] br_target;
|
||||
|
||||
wire [31:0] es_alu_src1 ;
|
||||
wire [31:0] es_alu_src2 ;
|
||||
wire [31:0] es_alu_result;
|
||||
wire es_Carry ;
|
||||
wire es_Sign ;
|
||||
wire es_Overflow ;
|
||||
wire es_Zero ;
|
||||
|
||||
assign br_bus = {br_taken,br_target};
|
||||
|
||||
assign es_to_ms_bus = {es_load_op , //75:71
|
||||
es_mem_to_reg , //70:70
|
||||
es_reg_we , //69:69
|
||||
es_dest , //68:64
|
||||
es_alu_result , //63:32
|
||||
es_pc //31:0
|
||||
};
|
||||
|
||||
assign es_ready_go = 1'b1;
|
||||
assign es_allowin = !es_valid || es_ready_go && ms_allowin;
|
||||
assign es_to_ms_valid = es_valid && es_ready_go;
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
es_valid <= 1'b0;
|
||||
end
|
||||
else if (es_allowin) begin
|
||||
es_valid <= ds_to_es_valid;
|
||||
end
|
||||
|
||||
if (ds_to_es_valid && es_allowin) begin
|
||||
ds_to_es_bus_r <= ds_to_es_bus;
|
||||
end
|
||||
end
|
||||
|
||||
assign es_alu_src1 = es_src1_is_pc ? es_pc :
|
||||
es_rf_rdata1;
|
||||
assign es_alu_src2 = es_src2_is_imm ? es_imm :
|
||||
es_src2_is_4 ? 32'd4 :
|
||||
es_rf_rdata2;
|
||||
|
||||
alu u_alu(
|
||||
.alu_op (es_alu_op ),
|
||||
.alu_src1 (es_alu_src1 ),
|
||||
.alu_src2 (es_alu_src2 ),
|
||||
.alu_result (es_alu_result),
|
||||
|
||||
.Carry (es_Carry ),
|
||||
.Sign (es_Sign ),
|
||||
.Overflow (es_Overflow ),
|
||||
.Zero (es_Zero )
|
||||
);
|
||||
|
||||
assign data_sram_en = 1'b1;
|
||||
assign data_sram_wen = (es_mem_we && es_valid) ? (({4{es_store_op[0]}} & ({4{es_alu_result[1:0] == 2'b00}} & 4'b0001)
|
||||
| ({4{es_alu_result[1:0] == 2'b01}} & 4'b0010)
|
||||
| ({4{es_alu_result[1:0] == 2'b10}} & 4'b0100)
|
||||
| ({4{es_alu_result[1:0] == 2'b11}} & 4'b1000))
|
||||
| ({4{es_store_op[1]}} & ({4{es_alu_result[1:0] == 2'b01}} & 4'b0011)
|
||||
| ({4{es_alu_result[1:0] == 2'b10}} & 4'b1100))
|
||||
| ({4{es_store_op[2]}} & 4'b1111 ))
|
||||
: 4'b0000;
|
||||
|
||||
assign data_sram_addr = es_alu_result;
|
||||
assign data_sram_wdata = es_store_op[0] ? {4{es_rf_rdata2[ 7:0]}} :
|
||||
es_store_op[1] ? {2{es_rf_rdata2[15:0]}} :
|
||||
es_store_op[2] ? es_rf_rdata2 :
|
||||
32'b0;
|
||||
|
||||
assign br_taken = ( es_branch_op[0] && es_Zero
|
||||
|| es_branch_op[1] && !es_Zero
|
||||
|| es_branch_op[2] && (es_Sign != es_Overflow)
|
||||
|| es_branch_op[3] && (es_Zero | (es_Sign == es_Overflow))
|
||||
|| es_branch_op[4] && es_Carry
|
||||
|| es_branch_op[5] && (es_Zero | ~es_Carry )
|
||||
|| es_branch_op[6]
|
||||
|| es_branch_op[7]
|
||||
|| es_branch_op[8]);
|
||||
assign br_target = (^es_branch_op[5:0]) ? (es_pc + es_imm) :
|
||||
( es_branch_op[7:6]) ? (es_pc + es_imm) :
|
||||
( es_branch_op[8] ) ? (es_rf_rdata1 + es_imm) :
|
||||
0;
|
||||
|
||||
endmodule
|
||||
247
lacpu/rtl/cpu/id_stage.v
Executable file
247
lacpu/rtl/cpu/id_stage.v
Executable file
@@ -0,0 +1,247 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
// 译码阶段
|
||||
module id_stage(
|
||||
input clk ,
|
||||
input reset ,
|
||||
//allowin
|
||||
input es_allowin ,
|
||||
output ds_allowin ,
|
||||
//from fs
|
||||
input fs_to_ds_valid,
|
||||
input [`FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus ,
|
||||
//to es
|
||||
output ds_to_es_valid,
|
||||
output [`DS_TO_ES_BUS_WD -1:0] ds_to_es_bus ,
|
||||
//to fs
|
||||
input [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus
|
||||
);
|
||||
|
||||
reg ds_valid ;
|
||||
wire ds_ready_go;
|
||||
|
||||
wire [31 :0] fs_pc;
|
||||
reg [`FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus_r;
|
||||
assign fs_pc = fs_to_ds_bus[31:0];
|
||||
|
||||
wire [31:0] ds_inst;
|
||||
wire [31:0] ds_pc ;
|
||||
assign {ds_inst,
|
||||
ds_pc } = fs_to_ds_bus_r;
|
||||
|
||||
wire rf_we ;
|
||||
wire [ 4:0] rf_waddr;
|
||||
wire [31:0] rf_wdata;
|
||||
assign {rf_we , //37:37
|
||||
rf_waddr, //36:32
|
||||
rf_wdata //31:0
|
||||
} = ws_to_rf_bus;
|
||||
|
||||
wire [11:0] alu_op;
|
||||
wire src1_is_pc;
|
||||
wire src2_is_imm;
|
||||
wire src2_is_4;
|
||||
wire mem_to_reg;
|
||||
wire reg_we;
|
||||
wire mem_we;
|
||||
wire [ 4:0] load_op;
|
||||
wire [ 2:0] store_op;
|
||||
wire [ 8:0] branch_op;
|
||||
wire [ 4:0] dest;
|
||||
wire [31:0] imm;
|
||||
|
||||
wire [21:0] op;
|
||||
wire [ 4:0] ra;
|
||||
wire [ 4:0] rk;
|
||||
wire [ 4:0] rj;
|
||||
wire [ 4:0] rd;
|
||||
wire [ 7:0] op6_d;
|
||||
wire [ 7:0] op7_d;
|
||||
wire [ 7:0] op10_d;
|
||||
wire [31:0] op17_d;
|
||||
|
||||
wire inst_addw;
|
||||
wire inst_subw;
|
||||
wire inst_addiw;
|
||||
wire inst_lu12iw;
|
||||
wire inst_slt;
|
||||
wire inst_sltu;
|
||||
wire inst_slti;
|
||||
wire inst_sltui;
|
||||
wire inst_pcaddu12i;
|
||||
wire inst_and;
|
||||
wire inst_or;
|
||||
wire inst_nor;
|
||||
wire inst_xor;
|
||||
wire inst_andi;
|
||||
wire inst_ori;
|
||||
wire inst_xori;
|
||||
wire inst_sllw;
|
||||
wire inst_srlw;
|
||||
wire inst_sraw;
|
||||
wire inst_slliw;
|
||||
wire inst_srliw;
|
||||
wire inst_beq;
|
||||
wire inst_bne;
|
||||
wire inst_blt;
|
||||
wire inst_bge;
|
||||
wire inst_bltu;
|
||||
wire inst_bgeu;
|
||||
wire inst_b;
|
||||
wire inst_bl;
|
||||
wire inst_jirl;
|
||||
wire inst_ldb;
|
||||
wire inst_ldh;
|
||||
wire inst_ldw;
|
||||
wire inst_ldbu;
|
||||
wire inst_ldhu;
|
||||
wire inst_stb;
|
||||
wire inst_sth;
|
||||
wire inst_stw;
|
||||
|
||||
wire dst_is_r1;
|
||||
|
||||
wire [ 4:0] rf_raddr1;
|
||||
wire [31:0] rf_rdata1;
|
||||
wire [ 4:0] rf_raddr2;
|
||||
wire [31:0] rf_rdata2;
|
||||
|
||||
wire rj_eq_rd;
|
||||
wire rj_lt_rd;
|
||||
wire rj_ltu_rd;
|
||||
|
||||
assign ds_to_es_bus = {alu_op , //158:147
|
||||
src1_is_pc , //146:146
|
||||
src2_is_imm , //145:145
|
||||
src2_is_4 , //144:144
|
||||
mem_to_reg , //143:143
|
||||
reg_we , //142:142
|
||||
mem_we , //141:141
|
||||
load_op , //140:136
|
||||
store_op , //135:133
|
||||
branch_op ,
|
||||
dest , //132:128
|
||||
imm , //127:96
|
||||
rf_rdata1 , //95 :64
|
||||
rf_rdata2 , //63 :32
|
||||
ds_pc //31 :0
|
||||
};
|
||||
|
||||
|
||||
assign ds_ready_go = 1'b1;
|
||||
assign ds_allowin = !ds_valid || ds_ready_go && es_allowin;
|
||||
assign ds_to_es_valid = ds_valid && ds_ready_go;
|
||||
always @(posedge clk) begin
|
||||
|
||||
if (reset) begin
|
||||
ds_valid <= 1'b0;
|
||||
end
|
||||
else if (ds_allowin) begin
|
||||
ds_valid <= fs_to_ds_valid;
|
||||
end
|
||||
|
||||
if (fs_to_ds_valid && ds_allowin) begin
|
||||
fs_to_ds_bus_r <= fs_to_ds_bus;
|
||||
end
|
||||
end
|
||||
|
||||
assign op = ds_inst[31:10];
|
||||
assign ra = ds_inst[19:15];
|
||||
assign rk = ds_inst[14:10];
|
||||
assign rj = ds_inst[ 9: 5];
|
||||
assign rd = ds_inst[ 4: 0];
|
||||
|
||||
decoder_3_8 u_dec0(.in(op[18:16]), .out(op6_d ));
|
||||
decoder_3_8 u_dec1(.in(op[17:15]), .out(op7_d ));
|
||||
decoder_3_8 u_dec2(.in(op[14:12]), .out(op10_d));
|
||||
decoder_5_32 u_dec3(.in(ra ), .out(op17_d));
|
||||
|
||||
assign inst_addw = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b00000];
|
||||
assign inst_subw = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b00001];
|
||||
assign inst_slt = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b00100];
|
||||
assign inst_sltu = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b00101];
|
||||
assign inst_nor = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b01000];
|
||||
assign inst_and = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b01001];
|
||||
assign inst_or = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b01010];
|
||||
assign inst_xor = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b01011];
|
||||
assign inst_sllw = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b01110];
|
||||
assign inst_srlw = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b01111];
|
||||
assign inst_sraw = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b10000];
|
||||
assign inst_slliw = (op[21: 5] == 12'b0000_0000_0100) & op17_d[5'b00001];
|
||||
assign inst_srliw = (op[21: 5] == 12'b0000_0000_0100) & op17_d[5'b01001];
|
||||
assign inst_sraiw = (op[21: 5] == 12'b0000_0000_0100) & op17_d[5'b10001];
|
||||
assign inst_slti = (op[21:11] == 7'b0000_001 ) & op10_d[3'b000];
|
||||
assign inst_sltui = (op[21:11] == 7'b0000_001 ) & op10_d[3'b001];
|
||||
assign inst_addiw = (op[21:11] == 7'b0000_001 ) & op10_d[3'b010];
|
||||
assign inst_andi = (op[21:11] == 7'b0000_001 ) & op10_d[3'b101];
|
||||
assign inst_ori = (op[21:11] == 7'b0000_001 ) & op10_d[3'b110];
|
||||
assign inst_xori = (op[21:11] == 7'b0000_001 ) & op10_d[3'b111];
|
||||
assign inst_ldb = (op[21:11] == 7'b0010_100 ) & op10_d[3'b000];
|
||||
assign inst_ldh = (op[21:11] == 7'b0010_100 ) & op10_d[3'b001];
|
||||
assign inst_ldw = (op[21:11] == 7'b0010_100 ) & op10_d[3'b010];
|
||||
assign inst_stb = (op[21:11] == 7'b0010_100 ) & op10_d[3'b100];
|
||||
assign inst_sth = (op[21:11] == 7'b0010_100 ) & op10_d[3'b101];
|
||||
assign inst_stw = (op[21:11] == 7'b0010_100 ) & op10_d[3'b110];
|
||||
assign inst_ldbu = (op[21:11] == 7'b0010_101 ) & op10_d[3'b000];
|
||||
assign inst_ldhu = (op[21:11] == 7'b0010_101 ) & op10_d[3'b001];
|
||||
assign inst_lu12iw = (op[21:17] == 4'b0001 ) & op7_d[3'b010];
|
||||
assign inst_pcaddu12i = (op[21:17] == 4'b0001 ) & op7_d[3'b110];
|
||||
assign inst_jirl = (op[21:15] == 3'b010 ) & op6_d[3'b011];
|
||||
assign inst_b = (op[21:15] == 3'b010 ) & op6_d[3'b100];
|
||||
assign inst_bl = (op[21:15] == 3'b010 ) & op6_d[3'b101];
|
||||
assign inst_beq = (op[21:15] == 3'b010 ) & op6_d[3'b110];
|
||||
assign inst_bne = (op[21:15] == 3'b010 ) & op6_d[3'b111];
|
||||
assign inst_blt = (op[21:15] == 3'b011 ) & op6_d[3'b000];
|
||||
assign inst_bge = (op[21:15] == 3'b011 ) & op6_d[3'b001];
|
||||
assign inst_bltu = (op[21:15] == 3'b011 ) & op6_d[3'b010];
|
||||
assign inst_bgeu = (op[21:15] == 3'b011 ) & op6_d[3'b011];
|
||||
|
||||
assign alu_op[ 0] = inst_addw | inst_addiw | inst_pcaddu12i | inst_ldb | inst_ldh | inst_ldbu | inst_ldhu | inst_ldw | inst_stb | inst_sth | inst_stw | inst_bl | inst_jirl;
|
||||
assign alu_op[ 1] = inst_subw;
|
||||
assign alu_op[ 2] = inst_slt | inst_slti;
|
||||
assign alu_op[ 3] = inst_sltu | inst_sltui;
|
||||
assign alu_op[ 4] = inst_and | inst_andi;
|
||||
assign alu_op[ 5] = inst_nor;
|
||||
assign alu_op[ 6] = inst_or | inst_ori;
|
||||
assign alu_op[ 7] = inst_xor | inst_xori;
|
||||
assign alu_op[ 8] = inst_sllw | inst_slliw;
|
||||
assign alu_op[ 9] = inst_srlw | inst_srliw;
|
||||
assign alu_op[10] = inst_sraw | inst_sraiw;
|
||||
assign alu_op[11] = inst_lu12iw;
|
||||
|
||||
assign imm = {32{inst_slti | inst_sltui | inst_addiw | inst_ldb | inst_ldh | inst_ldw | inst_stb | inst_sth | inst_stw | inst_ldbu | inst_ldhu}} & {{20{ds_inst[21]}}, ds_inst[21:10]}
|
||||
| {32{inst_beq | inst_bne | inst_bge | inst_bgeu | inst_blt | inst_bltu | inst_jirl}} & {{14{ds_inst[25]}}, ds_inst[25:10], 2'b0}
|
||||
| {32{inst_andi | inst_ori | inst_xori }} & { 20'b0 , ds_inst[21:10]}
|
||||
| {32{inst_lu12iw | inst_pcaddu12i }} & {{12{ds_inst[24]}}, ds_inst[24: 5]}
|
||||
| {32{inst_slliw | inst_srliw | inst_sraiw}} & { 27'b0 , rk}
|
||||
| {32{inst_b | inst_bl}} & {{4{ds_inst[9]}} , ds_inst[9:0], ds_inst[25:10], 2'b0};
|
||||
|
||||
assign src1_is_pc = inst_bl | inst_jirl | inst_pcaddu12i;
|
||||
assign src2_is_4 = inst_bl | inst_jirl;
|
||||
assign src2_is_imm = inst_addiw | inst_lu12iw | inst_pcaddu12i | inst_andi | inst_ori | inst_xori | inst_slliw | inst_srliw | inst_sraiw | inst_ldb | inst_ldh | inst_ldw | inst_ldbu | inst_ldhu | inst_stb | inst_sth | inst_stw;
|
||||
assign dst_is_r1 = inst_bl;
|
||||
|
||||
assign reg_we = ~(inst_beq | inst_bne | inst_bge | inst_bgeu | inst_blt | inst_bltu | inst_b | inst_stw | inst_sth | inst_stb);
|
||||
assign mem_we = inst_stw | inst_sth | inst_stb;
|
||||
assign mem_to_reg = inst_ldw | inst_ldh | inst_ldb | inst_ldhu | inst_ldbu;
|
||||
assign load_op = {inst_ldhu, inst_ldbu, inst_ldw, inst_ldh, inst_ldb};
|
||||
assign store_op = {inst_stw , inst_sth , inst_stb};
|
||||
assign branch_op = {inst_jirl, inst_bl , inst_b , inst_bgeu, inst_bltu, inst_bge, inst_blt, inst_bne, inst_beq};
|
||||
|
||||
assign dest = dst_is_r1 ? 5'd1 :
|
||||
rd;
|
||||
|
||||
assign rf_raddr1 = rj;
|
||||
assign rf_raddr2 = (inst_beq | inst_bne | inst_bge | inst_bgeu | inst_blt | inst_bltu) ? rd : rk;
|
||||
regfile u_regfile(
|
||||
.clk (clk ),
|
||||
.raddr1 (rf_raddr1),
|
||||
.rdata1 (rf_rdata1),
|
||||
.raddr2 (rf_raddr2),
|
||||
.rdata2 (rf_rdata2),
|
||||
.we (rf_we ),
|
||||
.waddr (rf_waddr ),
|
||||
.wdata (rf_wdata )
|
||||
);
|
||||
|
||||
endmodule
|
||||
71
lacpu/rtl/cpu/if_stage.v
Executable file
71
lacpu/rtl/cpu/if_stage.v
Executable file
@@ -0,0 +1,71 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
// 取指阶段
|
||||
module if_stage(
|
||||
input clk ,
|
||||
input reset ,
|
||||
//allwoin
|
||||
input ds_allowin ,
|
||||
//brbus
|
||||
input [`BR_BUS_WD -1:0] br_bus ,
|
||||
//to ds
|
||||
output fs_to_ds_valid ,
|
||||
output [`FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus ,
|
||||
// inst sram interface
|
||||
output inst_sram_en ,
|
||||
output [ 3:0] inst_sram_wen ,
|
||||
output [31:0] inst_sram_addr ,
|
||||
output [31:0] inst_sram_wdata,
|
||||
input [31:0] inst_sram_rdata
|
||||
);
|
||||
|
||||
reg fs_valid;
|
||||
wire fs_ready_go;
|
||||
wire fs_allowin;
|
||||
wire to_fs_valid;
|
||||
|
||||
wire [31:0] seq_pc;
|
||||
wire [31:0] nextpc;
|
||||
|
||||
wire br_taken;
|
||||
wire [ 31:0] br_target;
|
||||
assign {br_taken,br_target} = br_bus;
|
||||
|
||||
wire [31:0] fs_inst;
|
||||
reg [31:0] fs_pc;
|
||||
assign fs_to_ds_bus = {fs_inst ,
|
||||
fs_pc };
|
||||
|
||||
// pre-IF stage
|
||||
assign to_fs_valid = ~reset;
|
||||
assign seq_pc = fs_pc + 3'h4;
|
||||
assign nextpc = br_taken ? br_target : seq_pc;
|
||||
|
||||
// IF stage
|
||||
assign fs_ready_go = 1'b1;
|
||||
assign fs_allowin = !fs_valid || fs_ready_go && ds_allowin;
|
||||
assign fs_to_ds_valid = fs_valid && fs_ready_go;
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
fs_valid <= 1'b0;
|
||||
end
|
||||
else if (fs_allowin) begin
|
||||
fs_valid <= to_fs_valid;
|
||||
end
|
||||
|
||||
if (reset) begin
|
||||
fs_pc <= 32'h1bffffc; //to make nextpc be 0x1C000000 during reset
|
||||
end
|
||||
else if (to_fs_valid && fs_allowin) begin
|
||||
fs_pc <= nextpc;
|
||||
end
|
||||
end
|
||||
|
||||
assign inst_sram_en = to_fs_valid && fs_allowin;
|
||||
assign inst_sram_wen = 4'h0;
|
||||
assign inst_sram_addr = nextpc;
|
||||
assign inst_sram_wdata = 32'b0;
|
||||
|
||||
assign fs_inst = inst_sram_rdata;
|
||||
|
||||
endmodule
|
||||
75
lacpu/rtl/cpu/mem_stage.v
Executable file
75
lacpu/rtl/cpu/mem_stage.v
Executable file
@@ -0,0 +1,75 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module mem_stage(
|
||||
input clk ,
|
||||
input reset ,
|
||||
//allowin
|
||||
input ws_allowin ,
|
||||
output ms_allowin ,
|
||||
//from es
|
||||
input es_to_ms_valid,
|
||||
input [`ES_TO_MS_BUS_WD -1:0] es_to_ms_bus ,
|
||||
//to ws
|
||||
output ms_to_ws_valid,
|
||||
output [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus ,
|
||||
//from data-sram
|
||||
input [31 :0] data_sram_rdata
|
||||
);
|
||||
|
||||
reg ms_valid;
|
||||
wire ms_ready_go;
|
||||
|
||||
reg [`ES_TO_MS_BUS_WD -1:0] es_to_ms_bus_r;
|
||||
wire [ 4:0] ms_load_op;
|
||||
wire [ 2:0] ms_store_op;
|
||||
wire ms_mem_to_reg;
|
||||
wire ms_reg_we;
|
||||
wire [ 4:0] ms_dest;
|
||||
wire [31:0] ms_alu_result;
|
||||
wire [31:0] ms_pc;
|
||||
assign {ms_load_op , //75:71
|
||||
ms_mem_to_reg , //70:70
|
||||
ms_reg_we , //69:69
|
||||
ms_dest , //68:64
|
||||
ms_alu_result , //63:32
|
||||
ms_pc //31:0
|
||||
} = es_to_ms_bus_r;
|
||||
|
||||
wire [31:0] mem_result;
|
||||
wire [31:0] ms_final_result;
|
||||
|
||||
assign ms_to_ws_bus = {ms_reg_we , //69:69
|
||||
ms_dest , //68:64
|
||||
ms_final_result, //63:32
|
||||
ms_pc //31:0
|
||||
};
|
||||
|
||||
assign ms_ready_go = 1'b1;
|
||||
assign ms_allowin = !ms_valid || ms_ready_go && ws_allowin;
|
||||
assign ms_to_ws_valid = ms_valid && ms_ready_go;
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
ms_valid <= 1'b0;
|
||||
end
|
||||
else if (ms_allowin) begin
|
||||
ms_valid <= es_to_ms_valid;
|
||||
end
|
||||
|
||||
if (es_to_ms_valid && ms_allowin) begin
|
||||
es_to_ms_bus_r = es_to_ms_bus;
|
||||
end
|
||||
end
|
||||
|
||||
assign mem_result = (ms_load_op[0] || ms_load_op[3]) ? ((ms_alu_result[1:0] == 2'b00) ? {{24{ms_load_op[3] ? data_sram_rdata[ 7] : 1'b0 }}, data_sram_rdata[ 7:0] } :
|
||||
(ms_alu_result[1:0] == 2'b01) ? {{16{ms_load_op[3] ? data_sram_rdata[ 7] : 1'b0 }}, data_sram_rdata[ 7:0], 8'b0} :
|
||||
(ms_alu_result[1:0] == 2'b10) ? {{ 8{ms_load_op[3] ? data_sram_rdata[ 7] : 1'b0 }}, data_sram_rdata[ 7:0], 16'b0} :
|
||||
{ data_sram_rdata[ 7:0], 24'b0}) :
|
||||
(ms_load_op[1] || ms_load_op[4]) ? ((ms_alu_result[1:0] == 2'b00) ? {{16{ms_load_op[4] ? data_sram_rdata[15] : 1'b0 }}, data_sram_rdata[15:0] } :
|
||||
{ data_sram_rdata[15:0], 16'b0}) :
|
||||
ms_load_op[2] ? ( data_sram_rdata ) :
|
||||
32'b0;
|
||||
|
||||
assign ms_final_result = ms_mem_to_reg ? mem_result
|
||||
: ms_alu_result;
|
||||
|
||||
endmodule
|
||||
10
lacpu/rtl/cpu/mycpu.h
Executable file
10
lacpu/rtl/cpu/mycpu.h
Executable file
@@ -0,0 +1,10 @@
|
||||
`ifndef MYCPU_H
|
||||
`define MYCPU_H
|
||||
|
||||
`define BR_BUS_WD 33
|
||||
`define FS_TO_DS_BUS_WD 64
|
||||
`define DS_TO_ES_BUS_WD 159
|
||||
`define ES_TO_MS_BUS_WD 76
|
||||
`define MS_TO_WS_BUS_WD 70
|
||||
`define WS_TO_RF_BUS_WD 38
|
||||
`endif
|
||||
27
lacpu/rtl/cpu/regfile.v
Executable file
27
lacpu/rtl/cpu/regfile.v
Executable file
@@ -0,0 +1,27 @@
|
||||
module regfile(
|
||||
input clk,
|
||||
// READ PORT 1
|
||||
input [ 4:0] raddr1,
|
||||
output [31:0] rdata1,
|
||||
// READ PORT 2
|
||||
input [ 4:0] raddr2,
|
||||
output [31:0] rdata2,
|
||||
// WRITE PORT
|
||||
input we, //write enable, HIGH valid
|
||||
input [ 4:0] waddr,
|
||||
input [31:0] wdata
|
||||
);
|
||||
reg [31:0] rf[31:0];
|
||||
|
||||
//WRITE
|
||||
always @(posedge clk) begin
|
||||
if (we) rf[waddr]<= wdata;
|
||||
end
|
||||
|
||||
//READ OUT 1
|
||||
assign rdata1 = (raddr1==5'b0) ? 32'b0 : rf[raddr1];
|
||||
|
||||
//READ OUT 2
|
||||
assign rdata2 = (raddr2==5'b0) ? 32'b0 : rf[raddr2];
|
||||
|
||||
endmodule
|
||||
24
lacpu/rtl/cpu/tools.v
Executable file
24
lacpu/rtl/cpu/tools.v
Executable file
@@ -0,0 +1,24 @@
|
||||
module decoder_5_32(
|
||||
input [ 4:0] in,
|
||||
output [31:0] out
|
||||
);
|
||||
|
||||
genvar i;
|
||||
generate for (i=0; i<32; i=i+1) begin : gen_for_dec_5_32
|
||||
assign out[i] = (in == i);
|
||||
end endgenerate
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
module decoder_3_8(
|
||||
input [2:0] in,
|
||||
output [7:0] out
|
||||
);
|
||||
|
||||
genvar i;
|
||||
generate for (i=0; i<8; i=i+1) begin : gen_for_dec_3_8
|
||||
assign out[i] = (in == i);
|
||||
end endgenerate
|
||||
|
||||
endmodule
|
||||
67
lacpu/rtl/cpu/wb_stage.v
Executable file
67
lacpu/rtl/cpu/wb_stage.v
Executable file
@@ -0,0 +1,67 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module wb_stage(
|
||||
input clk ,
|
||||
input reset ,
|
||||
//allowin
|
||||
output ws_allowin ,
|
||||
//from ms
|
||||
input ms_to_ws_valid,
|
||||
input [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus ,
|
||||
//to rf: for write back
|
||||
output [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus ,
|
||||
//trace debug interface
|
||||
output [31:0] debug_wb_pc ,
|
||||
output [ 3:0] debug_wb_rf_wen ,
|
||||
output [ 4:0] debug_wb_rf_wnum,
|
||||
output [31:0] debug_wb_rf_wdata
|
||||
);
|
||||
|
||||
reg ws_valid;
|
||||
wire ws_ready_go;
|
||||
|
||||
reg [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus_r;
|
||||
wire ws_gr_we;
|
||||
wire [ 4:0] ws_dest;
|
||||
wire [31:0] ws_final_result;
|
||||
wire [31:0] ws_pc;
|
||||
assign {ws_reg_we , //69:69
|
||||
ws_dest , //68:64
|
||||
ws_final_result, //63:32
|
||||
ws_pc //31:0
|
||||
} = ms_to_ws_bus_r;
|
||||
|
||||
wire rf_we;
|
||||
wire [4 :0] rf_waddr;
|
||||
wire [31:0] rf_wdata;
|
||||
assign ws_to_rf_bus = {rf_we , //37:37
|
||||
rf_waddr, //36:32
|
||||
rf_wdata //31:0
|
||||
};
|
||||
|
||||
assign ws_ready_go = 1'b1;
|
||||
assign ws_allowin = !ws_valid || ws_ready_go;
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
ws_valid <= 1'b0;
|
||||
end
|
||||
else if (ws_allowin) begin
|
||||
ws_valid <= ms_to_ws_valid;
|
||||
end
|
||||
|
||||
if (ms_to_ws_valid && ws_allowin) begin
|
||||
ms_to_ws_bus_r <= ms_to_ws_bus;
|
||||
end
|
||||
end
|
||||
|
||||
assign rf_we = ws_reg_we && ws_valid;
|
||||
assign rf_waddr = ws_dest;
|
||||
assign rf_wdata = ws_final_result;
|
||||
|
||||
// debug info generate
|
||||
assign debug_wb_pc = ws_pc;
|
||||
assign debug_wb_rf_wen = {4{rf_we}};
|
||||
assign debug_wb_rf_wnum = ws_dest;
|
||||
assign debug_wb_rf_wdata = ws_final_result;
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user