Commit d36aadc8 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

rtl: some area optimizations

parent b9db4939
......@@ -43,6 +43,7 @@ module rv_exec
input d_valid_i,
input d_load_hazard_i,
input [4:0] d_opcode_i,
input d_shifter_sign_i,
......@@ -75,6 +76,7 @@ module rv_exec
output reg [31:0] f_branch_target_o,
output f_branch_take_o,
output w_load_hazard_o,
input irq_i,
......@@ -122,8 +124,8 @@ module rv_exec
reg [31:0] dm_addr, dm_data_s, dm_select_s;
wire [32:0] cmp_op1 = { d_is_signed_compare_i ? rs1[31] : 1'b0, rs1 };
wire [32:0] cmp_op2 = { d_is_signed_compare_i ? rs2[31] : 1'b0, rs2 };
wire [32:0] cmp_op1 = { d_is_signed_alu_op_i ? rs1[31] : 1'b0, rs1 };
wire [32:0] cmp_op2 = { d_is_signed_alu_op_i ? rs2[31] : 1'b0, rs2 };
wire [32:0] cmp_rs = cmp_op1 - cmp_op2;
......@@ -210,7 +212,7 @@ module rv_exec
// branch condition decoding
always@*
case (d_fun_i)
case (d_fun_i) // synthesis parallel_case full_case
`BRA_EQ: branch_condition_met <= cmp_equal;
`BRA_NEQ: branch_condition_met <= ~cmp_equal;
`BRA_GE: branch_condition_met <= ~cmp_lt | cmp_equal;
......@@ -219,27 +221,26 @@ module rv_exec
`BRA_LTU: branch_condition_met <= cmp_lt;
default: branch_condition_met <= 0;
endcase // case (d_fun_i)
// generate load/store address
always@*
dm_addr <= d_imm_i + ( ( d_opcode_i == `OPC_JALR || d_opcode_i == `OPC_LOAD || d_opcode_i == `OPC_STORE) ? rs1 : d_pc_i );
always@*
if(d_is_eret_i )
branch_target <= exception_address;
else if ( exception )
branch_target <= exception_vector;
else case (d_opcode_i)
`OPC_JAL: branch_target <= d_pc_i + d_imm_i;
`OPC_JALR: branch_target <= rs1 + d_imm_i;
`OPC_BRANCH: branch_target <= d_pc_i + d_imm_i;
default: branch_target<= 32'hx;
endcase // case (d_opcode_i)
// decode ALU operands
else
branch_target <= dm_addr;
// decode ALU operands
always@*
begin
alu_op1 <= d_use_op1_i ? d_alu_op1_i : rs1;
alu_op2 <= d_use_op2_i ? d_alu_op2_i : rs2;
end
wire [32:0] alu_addsub_op1 = {d_is_signed_alu_op_i ? alu_op1[31] : 1'b0, alu_op1 };
wire [32:0] alu_addsub_op2 = {d_is_signed_alu_op_i ? alu_op2[31] : 1'b0, alu_op2 };
......@@ -250,7 +251,7 @@ module rv_exec
alu_addsub_result <= alu_addsub_op1 + alu_addsub_op2;
else
alu_addsub_result <= alu_addsub_op1 - alu_addsub_op2;
// the ALU itself
always@*
......@@ -336,11 +337,6 @@ module rv_exec
default: rd_value <= 32'hx;
endcase // case (x_rd_source_i)
// generate load/store address
always@*
begin
dm_addr <= rs1 + { {20{d_imm_i[11]}}, d_imm_i[11:0] };
end
reg unaligned_addr;
......@@ -430,6 +426,7 @@ module rv_exec
w_load_o <= 0;
w_store_o <= 0;
w_valid_o <= 0;
end else if (!x_stall_i) begin
f_branch_target_o <= branch_target;
f_branch_take <= branch_take && !x_kill_i && d_valid_i;
......@@ -446,6 +443,7 @@ module rv_exec
assign f_branch_take_o = f_branch_take;
always@*
if(f_branch_take)
x_stall_req_o <= 0;
......@@ -456,6 +454,7 @@ module rv_exec
else
x_stall_req_o <= 0;
endmodule
......
......@@ -148,18 +148,13 @@ module rv_decode
end else
load_hazard <= 0;
reg inserting_nop = 0;
reg load_hazard_d;
reg inserting_nop;
always@(posedge clk_i)
if(rst_i) begin
inserting_nop <= 0;
load_hazard_d <= 0;
end else if (!d_stall_i)
begin
load_hazard_d <= load_hazard;
if (inserting_nop)
inserting_nop <= 0;
......@@ -169,7 +164,6 @@ module rv_decode
assign d_stall_req_o = load_hazard && !inserting_nop;
wire [4:0] f_rd = f_ir_i[11:7];
......@@ -213,14 +207,12 @@ module rv_decode
x_shifter_sign_o <= f_ir_i[30];
wire[31:0] d_imm_i = { {21{ f_ir_i[31] }}, f_ir_i[30:25], f_ir_i[24:21], f_ir_i[20] };
wire[31:0] d_imm_s = { {21{ f_ir_i[31] }}, f_ir_i[30:25], f_ir_i[11:8], f_ir_i[7] };
wire[31:0] d_imm_b = { {20{ f_ir_i[31] }}, f_ir_i[7], f_ir_i[30:25], f_ir_i[11:8], 1'b0 };
wire[31:0] d_imm_u = { f_ir_i[31], f_ir_i[30:20], f_ir_i[19:12], 12'h000 };
wire[31:0] d_imm_j = { {12{f_ir_i[31]}},
f_ir_i[19:12],
f_ir_i[20], f_ir_i[30:25], f_ir_i[24:21], 1'b0};
wire [31:0] d_imm_s = { {21{ f_ir_i[31] }}, f_ir_i[30:25], f_ir_i[11:8], f_ir_i[7] };
wire [31:0] d_imm_b = { {20{ f_ir_i[31] }}, f_ir_i[7], f_ir_i[30:25], f_ir_i[11:8], 1'b0 };
wire [31:0] d_imm_u = { f_ir_i[31], f_ir_i[30:20], f_ir_i[19:12], 12'h000 };
wire [31:0] d_imm_j = { {12{f_ir_i[31]}},
f_ir_i[19:12],
f_ir_i[20], f_ir_i[30:25], f_ir_i[24:21], 1'b0};
reg [31:0] d_imm;
......@@ -302,18 +294,42 @@ module rv_decode
x_is_load_o <= ( d_opcode == `OPC_LOAD && !load_hazard) ? 1'b1 : 1'b0;
x_is_store_o <= ( d_opcode == `OPC_STORE && !load_hazard) ? 1'b1 : 1'b0;
x_is_signed_compare_o <= ( ( d_opcode == `OPC_BRANCH) && ( ( d_fun == `BRA_GE )|| (d_fun == `BRA_LT ) ) )
|| ( ( (d_opcode == `OPC_OP) || (d_opcode == `OPC_OP_IMM) ) && (d_fun == `FUNC_SLT ) );
x_is_mul <= d_is_mul;
case (d_opcode)
`OPC_BRANCH:
x_is_signed_alu_op_o <= (d_fun == `BRA_GE || d_fun == `BRA_LT);
default:
x_is_signed_alu_op_o <= (d_fun == `FUNC_SLT);
endcase // case (d_opcode)
x_is_add_o <= (d_opcode == `OPC_AUIPC) || (d_opcode == `OPC_JAL) ||
case (d_opcode)
`OPC_OP:
x_is_add_o <= ~f_ir_i[30] && !(d_fun == `FUNC_SLT || d_fun == `FUNC_SLTU);
`OPC_OP_IMM:
x_is_add_o <= !(d_fun == `FUNC_SLT || d_fun == `FUNC_SLTU);
`OPC_BRANCH:
x_is_add_o <= 0;
default:
x_is_add_o <= 1;
endcase // case (d_opcode)
// x_is
// SUB instruction
// ~ ( d_opcode == OPC_OP &&
/*(d_opcode == `OPC_AUIPC) || (d_opcode == `OPC_JAL) ||
(d_opcode == `OPC_LUI) || (d_opcode == `OPC_JALR) ||
(!((d_opcode == `OPC_OP && d_fun == `FUNC_ADD && f_ir_i[30]) || (d_fun == `FUNC_SLT) || (d_fun == `FUNC_SLTU)));
(!((d_opcode == `OPC_OP && d_fun == `FUNC_ADD && f_ir_i[30]) || (d_fun == `FUNC_SLT) || (d_fun == `FUNC_SLTU)));*/
x_is_signed_alu_op_o <= (d_fun == `FUNC_SLT);
// all multiply/divide instructions except MUL
x_is_undef_o <= (d_opcode == `OPC_OP && f_ir_i[25] && d_fun != 3'b000);
......
......@@ -166,3 +166,125 @@ module rv_regfile
endmodule // rv_regfile
module rv_regmem_distram
(
input clk_i,
input [4:0] a1_i,
output [31:0] q1_o,
input [4:0] a2_i,
input [31:0] d2_i,
input we2_i
);
reg [31:0] ram [0:31];
assign q1_o = ram[a1_i];
always@(posedge clk_i)
if(we2_i)
ram[a2_i] <= d2_i;
// synthesis translate_off
initial begin : ram_init
integer i;
for(i=0;i<32; i=i+1) begin
ram[i] = 0;
end
end
// synthesis translate_on
endmodule // rv_regmem2
module rv_regfile_distram
(
input clk_i,
input rst_i,
input d_stall_i,
input [4:0] rf_rs1_i,
input [4:0] rf_rs2_i,
input [4:0] d_rs1_i,
input [4:0] d_rs2_i,
output reg [31:0] x_rs1_value_o,
output reg [31:0] x_rs2_value_o,
input [4:0] w_rd_i,
input [31:0] w_rd_value_i,
input w_rd_store_i,
input w_bypass_rd_write_i,
input [31:0] w_bypass_rd_value_i
);
wire [31:0] rs1_regfile;
wire [31:0] rs2_regfile;
wire write = (w_rd_store_i && (w_rd_i != 0));
rv_regmem_distram bank0 (
.clk_i(clk_i),
.a1_i(rf_rs1_i),
.q1_o(rs1_regfile),
.a2_i(w_rd_i),
.d2_i(w_rd_value_i),
.we2_i (write));
rv_regmem_distram bank1 (
.clk_i(clk_i),
.a1_i(rf_rs2_i),
.q1_o(rs2_regfile),
.a2_i (w_rd_i),
.d2_i (w_rd_value_i),
.we2_i (write)
);
wire rs1_bypass_x = w_bypass_rd_write_i && (w_rd_i == d_rs1_i) && (w_rd_i != 0);
wire rs2_bypass_x = w_bypass_rd_write_i && (w_rd_i == d_rs2_i) && (w_rd_i != 0);
reg rs1_bypass_w, rs2_bypass_w;
always@*
begin
rs1_bypass_w <= write && (rf_rs1_i == w_rd_i);
rs2_bypass_w <= write && (rf_rs2_i == w_rd_i);
end
always@(posedge clk_i)
if(!d_stall_i)
begin
case ( {rs1_bypass_x, rs1_bypass_w } ) // synthesis parallel_case full_case
2'b10, 2'b11:
x_rs1_value_o <= w_bypass_rd_value_i;
2'b01:
x_rs1_value_o <= w_rd_value_i;
default:
x_rs1_value_o <= rs1_regfile;
endcase // case ( {rs1_bypass_x, rs1_bypass_w } )
case ( {rs2_bypass_x, rs2_bypass_w } ) // synthesis parallel_case full_case
2'b10, 2'b11:
x_rs2_value_o <= w_bypass_rd_value_i;
2'b01:
x_rs2_value_o <= w_rd_value_i;
default:
x_rs2_value_o <= rs2_regfile;
endcase // case ( {rs2_bypass_x, rs2_bypass_w } )
end // always@ *
endmodule // rv_regfile
#vlog -sv main.sv +incdir+. +incdir+../../include/wb +incdir+../../include/vme64x_bfm +incdir+../../include +incdir+../include +incdir+../../sim
vsim -t 1ps work.main -novopt
vsim -L unisim -t 1ps work.main -novopt
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
......
This diff is collapsed.
......@@ -49,6 +49,14 @@ module main;
int f = $fopen(filename,"r");
int n, i;
if( f == 0)
begin
$error("can't open: %s", filename);
$stop;
end
while(!$feof(f))
begin
int addr, data;
......
#vlog -sv main.sv +incdir+. +incdir+../../include/wb +incdir+../../include/vme64x_bfm +incdir+../../include +incdir+../include +incdir+../../sim
vsim -t 1ps work.main -novopt
vsim -L unisim -t 1ps work.main -novopt
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment