Commit 17e87946 authored by Koen Martens's avatar Koen Martens

cpu: finalize constant-time unsigned multiplication

parent b4058a54
Pipeline #2 failed with stages
......@@ -85,11 +85,10 @@ module cpu
reg [DATA_WIDTH-1:0] opcode1;
reg [DATA_WIDTH-1:0] opcode2;
reg [(DATA_WIDTH*2)-1:0] multiplicant;
reg [(DATA_WIDTH*2)-1:0] multiplicand;
reg [DATA_WIDTH-1:0] multiplier;
reg [(DATA_WIDTH*2)-1:0] product;
reg [3:0] multiply_iteration;
wire multiplication_end = multiply_iteration[3];
// opcode decoding shortcuts
......@@ -174,10 +173,8 @@ module cpu
localparam STATE_PUSH_REG_WAIT = 'b01011;
localparam STATE_POP_REG_WAIT = 'b01100;
localparam STATE_MUL_ITER = 'b01101;
localparam STATE_MUL_ADD_LSB = 'b01110;
localparam STATE_MUL_ADD_MSB = 'b01111;
localparam STATE_MUL_SHIFT = 'b10000;
localparam STATE_MUL_DONE = 'b10001;
localparam STATE_MUL_ADD = 'b01110;
localparam STATE_MUL_DONE = 'b01111;
localparam STATE_HALTED = 'b11111;
integer i;
......@@ -329,9 +326,9 @@ module cpu
alu_op = opcode2[OPCODE2_BIT_SUB] ? `ALU_OP_SUB : `ALU_OP_ADD;
state = STATE_STORE_ALU_OUT;
end else if(alu_opcode == ALU_OPCODE_MUL) begin
//multiplicant[(DATA_WIDTH*2)-1:DATA_WIDTH] = {DATA_WIDTH{r[reg_ddd][DATA_WIDTH-1]}};
multiplicant[(DATA_WIDTH*2)-1:DATA_WIDTH] = 'b0; //{DATA_WIDTH{r[reg_ddd][DATA_WIDTH-1]}};
multiplicant[DATA_WIDTH-1:0] = r[reg_ddd];
multiplicand[(DATA_WIDTH*2)-1:DATA_WIDTH] = r[reg_ddd];
multiplicand[DATA_WIDTH-1:0] = 'b0;
// = {r[reg_ddd], {DATA_WIDTH{1'b0}}};
multiplier = r[reg_sss];
multiply_iteration = 'b0;
product = 'b0;
......@@ -428,38 +425,26 @@ module cpu
end
STATE_MUL_ITER:
begin
$display("%d: %H %H (%H * %H)", multiply_iteration, product[(DATA_WIDTH*2)-1:DATA_WIDTH], product[DATA_WIDTH-1:0], multiplicant, multiplier);
$display("%d: %H %H (%b * %b)", multiply_iteration, product[(DATA_WIDTH*2)-1:DATA_WIDTH], product[DATA_WIDTH-1:0], multiplicand, multiplier);
if (multiplier[0]) begin
alu_in1 = product[DATA_WIDTH-1:0];
alu_in2 = multiplicant[DATA_WIDTH-1:0];
alu_carry_in = 1'b0;
alu_op = `ALU_OP_ADD;
state = STATE_MUL_ADD_LSB;
alu_in2 = multiplicand[(DATA_WIDTH*2)-1:DATA_WIDTH];
end else begin
state = STATE_MUL_SHIFT;
alu_in2 = 'b0;
end
end
STATE_MUL_ADD_LSB:
begin
product[DATA_WIDTH-1:0] = alu_out;
alu_in1 = product[(DATA_WIDTH*2)-1:DATA_WIDTH];
alu_in2 = multiplicant[(DATA_WIDTH*2)-1:DATA_WIDTH];
alu_carry_in = alu_carry;
alu_carry_in = 1'b0;
alu_op = `ALU_OP_ADD;
state = STATE_MUL_ADD_MSB;
state = STATE_MUL_ADD;
end
STATE_MUL_ADD_MSB:
begin
product[(DATA_WIDTH*2)-1:DATA_WIDTH] = alu_out;
state = STATE_MUL_SHIFT;
end
STATE_MUL_SHIFT:
STATE_MUL_ADD:
begin
$display(" alu_in1=%H, alu_in2=%H, alu_out=%H, alu_carry=%b", alu_in1, alu_in2, alu_out, alu_carry);
$display(" : %H %H", product[(DATA_WIDTH*2)-1:DATA_WIDTH], product[DATA_WIDTH-1:0]);
multiplicant = multiplicant << 1;
multiplier = multiplier >> 1;
product[(DATA_WIDTH*2)-1:DATA_WIDTH] = alu_out;
product = { alu_carry, alu_out, product[DATA_WIDTH-1:1] };
multiply_iteration = multiply_iteration + 1;
state = (multiply_iteration==8) ? STATE_MUL_DONE : STATE_MUL_ITER;
state = (multiply_iteration[$clog2(DATA_WIDTH)]) ? STATE_MUL_DONE : STATE_MUL_ITER;
end
STATE_MUL_DONE:
begin
......
......@@ -768,13 +768,13 @@ module cpu_tb();
double_opcode_response('h0002, 'h81, 'h23, "mul 1 0008: imm r1, 'h23");
double_opcode_response('h0004, 'he2, 'h81, "mul 1 000a: mul r0, r1");
@(posedge tb_stb_o);
tb_assert(UUT.r[0] === 'h23, "result mul 1 42+23+1 = 66");
tb_assert(UUT.r[1] === 'h00, "result mul 1 42+23+1 = 66");
tb_assert(UUT.sr[UUT.SR_BIT_ZERO] === 'b0, "mul 1 42+43+1, not zero");
tb_assert(UUT.sr[UUT.SR_BIT_CARRY] === 'b0, "mul 1 42+43+1, no carry");
tb_assert(UUT.sr[UUT.SR_BIT_OVERFLOW] === 'b0, "mul 1 42+43+1, no overflow");
tb_assert(UUT.sr[UUT.SR_BIT_PARITY] === 'b0, "mul 1 42+43+1, no parity");
tb_assert(UUT.sr[UUT.SR_BIT_NEGATIVE] === 'b0, "mul 1 42+43+1, not negative");
tb_assert(UUT.r[0] === 'h23, "result mul 1 01*23 = 66");
tb_assert(UUT.r[1] === 'h00, "result mul 1 01*23 = 66");
tb_assert(UUT.sr[UUT.SR_BIT_ZERO] === 'b0, "mul 1 01*23, not zero");
tb_assert(UUT.sr[UUT.SR_BIT_CARRY] === 'b0, "mul 1 01*23, no carry");
tb_assert(UUT.sr[UUT.SR_BIT_OVERFLOW] === 'b0, "mul 1 01*23, no overflow");
tb_assert(UUT.sr[UUT.SR_BIT_PARITY] === 'b0, "mul 1 01*23, no parity");
tb_assert(UUT.sr[UUT.SR_BIT_NEGATIVE] === 'b0, "mul 1 01*23, not negative");
tb_rst_i = 1'b1;
@(posedge clk);
......
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