[Add] add div.w[u], mod.w[u]
This commit is contained in:
@@ -15,6 +15,24 @@ module mycpu_top(
|
||||
output [31:0] data_sram_addr,
|
||||
output [31:0] data_sram_wdata,
|
||||
input [31:0] data_sram_rdata,
|
||||
//div
|
||||
output [31:0] div_divisor_data,
|
||||
output div_divisor_valid,
|
||||
input div_divisor_ready,
|
||||
output [31:0] div_dividend_data,
|
||||
output div_dividend_valid,
|
||||
input div_dividend_ready,
|
||||
input div_dout_valid,
|
||||
input [63:0] div_dout_data,
|
||||
//divu
|
||||
output [31:0] divu_divisor_data,
|
||||
output divu_divisor_valid,
|
||||
input divu_divisor_ready,
|
||||
output [31:0] divu_dividend_data,
|
||||
output divu_dividend_valid,
|
||||
input divu_dividend_ready,
|
||||
input divu_dout_valid,
|
||||
input [63:0] divu_dout_data,
|
||||
// trace debug interface
|
||||
output [31:0] debug_wb_pc,
|
||||
output [ 3:0] debug_wb_rf_wen,
|
||||
@@ -107,7 +125,25 @@ module mycpu_top(
|
||||
.data_sram_en (data_sram_en ),
|
||||
.data_sram_wen (data_sram_wen ),
|
||||
.data_sram_addr (data_sram_addr ),
|
||||
.data_sram_wdata(data_sram_wdata)
|
||||
.data_sram_wdata(data_sram_wdata),
|
||||
//div
|
||||
.div_divisor_data (div_divisor_data ),
|
||||
.div_divisor_valid (div_divisor_valid ),
|
||||
.div_divisor_ready (div_divisor_ready ),
|
||||
.div_dividend_data (div_dividend_data ),
|
||||
.div_dividend_valid (div_dividend_valid ),
|
||||
.div_dividend_ready (div_dividend_ready ),
|
||||
.div_dout_valid (div_dout_valid ),
|
||||
.div_dout_data (div_dout_data ),
|
||||
//divu
|
||||
.divu_divisor_data (divu_divisor_data ),
|
||||
.divu_divisor_valid (divu_divisor_valid ),
|
||||
.divu_divisor_ready (divu_divisor_ready ),
|
||||
.divu_dividend_data (divu_dividend_data ),
|
||||
.divu_dividend_valid(divu_dividend_valid),
|
||||
.divu_dividend_ready(divu_dividend_ready),
|
||||
.divu_dout_valid (divu_dout_valid ),
|
||||
.divu_dout_data (divu_dout_data )
|
||||
);
|
||||
// MEM stage
|
||||
mem_stage mem_stage(
|
||||
|
||||
@@ -24,14 +24,32 @@ module exe_stage(
|
||||
//from ms
|
||||
input [`MS_TO_ES_BUS_WD -1:0] ms_to_ds_bus ,
|
||||
//from ws
|
||||
input [`WS_TO_ES_BUS_WD -1:0] ws_to_ds_bus
|
||||
input [`WS_TO_ES_BUS_WD -1:0] ws_to_ds_bus ,
|
||||
//div
|
||||
output [31:0] div_divisor_data ,
|
||||
output div_divisor_valid ,
|
||||
input div_divisor_ready ,
|
||||
output [31:0] div_dividend_data ,
|
||||
output div_dividend_valid ,
|
||||
input div_dividend_ready ,
|
||||
input div_dout_valid ,
|
||||
input [63:0] div_dout_data ,
|
||||
//divu
|
||||
output [31:0] divu_divisor_data ,
|
||||
output divu_divisor_valid ,
|
||||
input divu_divisor_ready ,
|
||||
output [31:0] divu_dividend_data ,
|
||||
output divu_dividend_valid ,
|
||||
input divu_dividend_ready ,
|
||||
input divu_dout_valid ,
|
||||
input [63:0] divu_dout_data
|
||||
);
|
||||
|
||||
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 [18:0] es_alu_op;
|
||||
wire es_src1_is_pc;
|
||||
wire es_src2_is_imm;
|
||||
wire es_src2_is_4;
|
||||
@@ -56,8 +74,7 @@ module exe_stage(
|
||||
wire es_src2_is_ms_dest;
|
||||
wire es_data_is_rf_wdata;
|
||||
|
||||
|
||||
assign {es_alu_op , //169:155
|
||||
assign {es_alu_op , //173:155
|
||||
es_src1_is_pc , //154:154
|
||||
es_src2_is_imm , //153:153
|
||||
es_src2_is_4 , //152:152
|
||||
@@ -93,6 +110,26 @@ module exe_stage(
|
||||
wire es_Sign ;
|
||||
wire es_Overflow ;
|
||||
wire es_Zero ;
|
||||
wire [31:0] es_result ;
|
||||
|
||||
reg div_divisor_valid_reg;
|
||||
reg div_divisor_ready_flag;
|
||||
reg div_dividend_valid_reg;
|
||||
reg div_dividend_ready_flag;
|
||||
reg divu_divisor_valid_reg;
|
||||
reg divu_divisor_ready_flag;
|
||||
reg divu_dividend_valid_reg;
|
||||
reg divu_dividend_ready_flag;
|
||||
|
||||
wire es_inst_divw ;
|
||||
wire es_inst_modw ;
|
||||
wire es_inst_divwu;
|
||||
wire es_inst_modwu;
|
||||
wire is_div_mod;
|
||||
|
||||
wire [31:0] div_mod_result;
|
||||
|
||||
assign es_result = is_div_mod ? div_mod_result : es_alu_result;
|
||||
|
||||
assign es_to_ms_bus = {br_target , //120:89
|
||||
es_branch_op , //88 :80
|
||||
@@ -104,7 +141,7 @@ module exe_stage(
|
||||
es_mem_to_reg , //70 :70
|
||||
es_reg_we , //69 :69
|
||||
es_dest , //68 :64
|
||||
es_alu_result , //63 :32
|
||||
es_result , //63 :32
|
||||
es_pc //31 :0
|
||||
};
|
||||
|
||||
@@ -114,7 +151,7 @@ module exe_stage(
|
||||
es_mem_we
|
||||
};
|
||||
|
||||
assign es_ready_go = 1'b1;
|
||||
assign es_ready_go = (is_div_mod && !(div_dout_valid || divu_dout_valid)) ? 1'b1 : 1'b0;
|
||||
assign es_allowin = !es_valid || es_ready_go && ms_allowin;
|
||||
assign es_to_ms_valid = es_valid && es_ready_go;
|
||||
always @(posedge clk) begin
|
||||
@@ -140,8 +177,95 @@ module exe_stage(
|
||||
es_src2_is_ms_dest ? ws_rf_wdata :
|
||||
es_rf_rdata2;
|
||||
|
||||
assign is_div_mod = es_inst_divw | es_inst_modw | es_inst_divwu | es_inst_modwu;
|
||||
assign es_inst_divw = es_alu_op[15];
|
||||
assign es_inst_modw = es_alu_op[16];
|
||||
assign es_inst_divwu = es_alu_op[17];
|
||||
assign es_inst_modwu = es_alu_op[18];
|
||||
|
||||
assign div_divisor_data = es_alu_src1;
|
||||
assign div_dividend_data = es_alu_src2;
|
||||
assign divu_divisor_data = es_alu_src1;
|
||||
assign divu_dividend_data = es_alu_src2;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(reset) begin
|
||||
div_divisor_valid_reg <= 0'b0;
|
||||
div_divisor_ready_flag <= 0'b0;
|
||||
end
|
||||
else if(div_divisor_valid_reg && div_divisor_ready) begin
|
||||
div_divisor_valid_reg <= 0'b0;
|
||||
div_divisor_ready_flag <= 0'b1;
|
||||
end
|
||||
else if((es_inst_divw || es_inst_modw) && !div_divisor_ready_flag) begin
|
||||
div_divisor_valid_reg <= 0'b1;
|
||||
end
|
||||
else if(es_ready_go) begin
|
||||
div_divisor_ready_flag <= 1'b0;
|
||||
end
|
||||
end
|
||||
always @(posedge clk) begin
|
||||
if(reset) begin
|
||||
div_dividend_valid_reg <= 0'b0;
|
||||
div_dividend_ready_flag <= 0'b0;
|
||||
end
|
||||
else if(div_dividend_valid_reg && div_dividend_ready) begin
|
||||
div_dividend_valid_reg <= 0'b0;
|
||||
div_dividend_ready_flag <= 0'b1;
|
||||
end
|
||||
else if((es_inst_divw || es_inst_modw) && !div_dividend_ready_flag) begin
|
||||
div_dividend_valid_reg <= 0'b1;
|
||||
end
|
||||
else if(es_ready_go) begin
|
||||
div_dividend_ready_flag <= 1'b0;
|
||||
end
|
||||
end
|
||||
always @(posedge clk) begin
|
||||
if(reset) begin
|
||||
divu_divisor_valid_reg <= 0'b0;
|
||||
divu_divisor_ready_flag <= 0'b0;
|
||||
end
|
||||
else if(divu_divisor_valid_reg && divu_divisor_ready) begin
|
||||
divu_divisor_valid_reg <= 0'b0;
|
||||
divu_divisor_ready_flag <= 0'b1;
|
||||
end
|
||||
else if((es_inst_divw || es_inst_modw) && !divu_divisor_ready_flag) begin
|
||||
divu_divisor_valid_reg <= 0'b1;
|
||||
end
|
||||
else if(es_ready_go) begin
|
||||
divu_divisor_ready_flag <= 1'b0;
|
||||
end
|
||||
end
|
||||
always @(posedge clk) begin
|
||||
if(reset) begin
|
||||
divu_dividend_valid_reg <= 0'b0;
|
||||
divu_dividend_ready_flag <= 0'b0;
|
||||
end
|
||||
else if(divu_dividend_valid_reg && divu_dividend_ready) begin
|
||||
divu_dividend_valid_reg <= 0'b0;
|
||||
divu_dividend_ready_flag <= 0'b1;
|
||||
end
|
||||
else if((es_inst_divw || es_inst_modw) && !divu_dividend_ready_flag) begin
|
||||
divu_dividend_valid_reg <= 0'b1;
|
||||
end
|
||||
else if(es_ready_go) begin
|
||||
divu_dividend_ready_flag <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
assign div_divisor_valid = div_divisor_valid_reg;
|
||||
assign div_dividend_valid = div_dividend_valid_reg;
|
||||
assign divu_divisor_valid = divu_divisor_valid_reg;
|
||||
assign divu_dividend_valid = divu_dividend_valid_reg;
|
||||
|
||||
assign div_mod_result = es_inst_divw ? div_dout_data[63:32] :
|
||||
es_inst_modw ? div_dout_data[31: 0] :
|
||||
es_inst_divwu ? divu_dout_data[63:32] :
|
||||
es_inst_modwu ? divu_dout_data[31: 0] :
|
||||
32'b0;
|
||||
|
||||
alu u_alu(
|
||||
.alu_op (es_alu_op ),
|
||||
.alu_op (es_alu_op[14:0]),
|
||||
.alu_src1 (es_alu_src1 ),
|
||||
.alu_src2 (es_alu_src2 ),
|
||||
.alu_result (es_alu_result),
|
||||
|
||||
@@ -31,7 +31,7 @@ module forward(
|
||||
wire data_is_rf_wdata;
|
||||
|
||||
assign {ds_rf_raddr1, ds_rf_raddr2 } = ds_to_fw_bus_r;
|
||||
assign {es_rf_rdata2, es_dest, es_reg_we, es_mem_we} = es_to_fw_bus_r;
|
||||
assign {es_rf_raddr2, es_dest, es_reg_we, es_mem_we} = es_to_fw_bus_r;
|
||||
assign {ms_dest , ms_reg_we} = ms_to_fw_bus_r;
|
||||
|
||||
assign fw_to_es_bus = {src1_is_es_dest , //4:4
|
||||
|
||||
@@ -40,7 +40,7 @@ module id_stage(
|
||||
rf_wdata //31:0
|
||||
} = ws_to_rf_bus;
|
||||
|
||||
wire [14:0] alu_op;
|
||||
wire [18:0] alu_op;
|
||||
wire src1_is_pc;
|
||||
wire src2_is_imm;
|
||||
wire src2_is_4;
|
||||
@@ -84,6 +84,10 @@ module id_stage(
|
||||
wire inst_sraw;
|
||||
wire inst_slliw;
|
||||
wire inst_srliw;
|
||||
wire inst_sraiw;
|
||||
wire inst_mulw;
|
||||
wire inst_mulhw;
|
||||
wire inst_mulhwu;
|
||||
wire inst_beq;
|
||||
wire inst_bne;
|
||||
wire inst_blt;
|
||||
@@ -101,6 +105,12 @@ module id_stage(
|
||||
wire inst_stb;
|
||||
wire inst_sth;
|
||||
wire inst_stw;
|
||||
wire inst_divw;
|
||||
wire inst_modw;
|
||||
wire inst_divwu;
|
||||
wire inst_modwu;
|
||||
|
||||
|
||||
|
||||
wire dst_is_r1;
|
||||
|
||||
@@ -113,7 +123,7 @@ module id_stage(
|
||||
wire rj_lt_rd;
|
||||
wire rj_ltu_rd;
|
||||
|
||||
assign ds_to_es_bus = {alu_op , //169:155
|
||||
assign ds_to_es_bus = {alu_op , //173:155
|
||||
src1_is_pc , //154:154
|
||||
src2_is_imm , //153:153
|
||||
src2_is_4 , //152:152
|
||||
@@ -177,6 +187,10 @@ module id_stage(
|
||||
assign inst_mulw = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b11000];
|
||||
assign inst_mulhw = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b11001];
|
||||
assign inst_mulhwu = (op[21: 5] == 12'b0000_0000_0001) & op17_d[5'b11010];
|
||||
assign inst_divw = (op[21: 5] == 12'b0000_0000_0010) & op17_d[5'b00000];
|
||||
assign inst_modw = (op[21: 5] == 12'b0000_0000_0010) & op17_d[5'b00001];
|
||||
assign inst_divwu = (op[21: 5] == 12'b0000_0000_0010) & op17_d[5'b00010];
|
||||
assign inst_modwu = (op[21: 5] == 12'b0000_0000_0010) & op17_d[5'b00011];
|
||||
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];
|
||||
@@ -203,9 +217,6 @@ module id_stage(
|
||||
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;
|
||||
@@ -221,6 +232,10 @@ module id_stage(
|
||||
assign alu_op[12] = inst_mulw;
|
||||
assign alu_op[13] = inst_mulhw;
|
||||
assign alu_op[14] = inst_mulhwu;
|
||||
assign alu_op[15] = inst_divw;
|
||||
assign alu_op[16] = inst_modw;
|
||||
assign alu_op[17] = inst_divwu;
|
||||
assign alu_op[18] = inst_modwu;
|
||||
|
||||
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}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
`define BR_BUS_WD 33
|
||||
`define FS_TO_DS_BUS_WD 64
|
||||
`define DS_TO_ES_BUS_WD 170
|
||||
`define DS_TO_ES_BUS_WD 174
|
||||
`define ES_TO_MS_BUS_WD 121
|
||||
`define MS_TO_WS_BUS_WD 70
|
||||
`define WS_TO_RF_BUS_WD 38
|
||||
|
||||
@@ -33,7 +33,25 @@ module soc_lite_top
|
||||
wire [31:0] cpu_data_addr;
|
||||
wire [31:0] cpu_data_wdata;
|
||||
wire [31:0] cpu_data_rdata;
|
||||
|
||||
//div
|
||||
wire [31:0] div_divisor_data;
|
||||
wire div_divisor_valid;
|
||||
wire div_divisor_ready;
|
||||
wire [31:0] div_dividend_data;
|
||||
wire div_dividend_valid;
|
||||
wire div_dividend_ready;
|
||||
wire div_dout_valid;
|
||||
wire [63:0] div_dout_data;
|
||||
//divu
|
||||
wire [31:0] divu_divisor_data;
|
||||
wire divu_divisor_valid;
|
||||
wire divu_divisor_ready;
|
||||
wire [31:0] divu_dividend_data;
|
||||
wire divu_dividend_valid;
|
||||
wire divu_dividend_ready;
|
||||
wire divu_dout_valid;
|
||||
wire [63:0] divu_dout_data;
|
||||
|
||||
//cpu
|
||||
mycpu_top cpu(
|
||||
.clk (cpu_clk ),
|
||||
@@ -51,6 +69,25 @@ module soc_lite_top
|
||||
.data_sram_wdata (cpu_data_wdata),
|
||||
.data_sram_rdata (cpu_data_rdata),
|
||||
|
||||
//div
|
||||
.div_divisor_data (div_divisor_data ),
|
||||
.div_divisor_valid (div_divisor_valid ),
|
||||
.div_divisor_ready (div_divisor_ready ),
|
||||
.div_dividend_data (div_dividend_data ),
|
||||
.div_dividend_valid (div_dividend_valid ),
|
||||
.div_dividend_ready (div_dividend_ready ),
|
||||
.div_dout_valid (div_dout_valid ),
|
||||
.div_dout_data (div_dout_data ),
|
||||
//divu
|
||||
.divu_divisor_data (divu_divisor_data ),
|
||||
.divu_divisor_valid (divu_divisor_valid ),
|
||||
.divu_divisor_ready (divu_divisor_ready ),
|
||||
.divu_dividend_data (divu_dividend_data ),
|
||||
.divu_dividend_valid(divu_dividend_valid),
|
||||
.divu_dividend_ready(divu_dividend_ready),
|
||||
.divu_dout_valid (divu_dout_valid ),
|
||||
.divu_dout_data (divu_dout_data ),
|
||||
|
||||
//debug
|
||||
.debug_wb_pc (debug_wb_pc ),
|
||||
.debug_wb_rf_wen (debug_wb_rf_wen ),
|
||||
@@ -84,6 +121,32 @@ module soc_lite_top
|
||||
.dina (cpu_data_wdata ), //31:0
|
||||
.douta (cpu_data_rdata ) //31:0
|
||||
);
|
||||
|
||||
//div
|
||||
div div(
|
||||
.aclk (cpu_clk ),
|
||||
.s_axis_divisor_tdata (div_divisor_data ),
|
||||
.s_axis_divisor_tvalid (div_divisor_valid ),
|
||||
.s_axis_divisor_tready (div_divisor_ready ),
|
||||
.s_axis_dividend_tdata (div_dividend_data ),
|
||||
.s_axis_dividend_tvalid (div_dividend_valid ),
|
||||
.s_axis_dividend_tready (div_dividend_ready ),
|
||||
.m_axis_dout_tvalid (div_dout_valid ),
|
||||
.m_axis_dout_tdata (div_dout_data )
|
||||
);
|
||||
|
||||
//divu
|
||||
divu divu(
|
||||
.aclk (cpu_clk ),
|
||||
.s_axis_divisor_tdata (divu_divisor_data ),
|
||||
.s_axis_divisor_tvalid (divu_divisor_valid ),
|
||||
.s_axis_divisor_tready (divu_divisor_ready ),
|
||||
.s_axis_dividend_tdata (divu_dividend_data ),
|
||||
.s_axis_dividend_tvalid (divu_dividend_valid),
|
||||
.s_axis_dividend_tready (divu_dividend_ready),
|
||||
.m_axis_dout_tvalid (divu_dout_valid ),
|
||||
.m_axis_dout_tdata (divu_dout_data )
|
||||
);
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user