diff options
| author | Alejandro Soto <alejandro@34project.org> | 2022-11-06 12:22:37 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2022-11-06 12:34:25 -0600 |
| commit | 044d2d73f0fbe6e1e42934f01b0f339776881b55 (patch) | |
| tree | 358703da80e67f09e8d7824b35af13accaaa676f /rtl/core | |
| parent | ff5f2a94c06ce3af9cc04033220dcd0f6c8826e3 (diff) | |
Add multiplier unit
Diffstat (limited to 'rtl/core')
| -rw-r--r-- | rtl/core/arm810.sv | 22 | ||||
| -rw-r--r-- | rtl/core/mul.sv | 182 | ||||
| -rw-r--r-- | rtl/core/uarch.sv | 1 |
3 files changed, 72 insertions, 133 deletions
diff --git a/rtl/core/arm810.sv b/rtl/core/arm810.sv index 3bc2769..b3dd92e 100644 --- a/rtl/core/arm810.sv +++ b/rtl/core/arm810.sv @@ -125,9 +125,27 @@ module arm810 .c(c_shifter) ); - //TODO logic mul, mul_add, mul_long, mul_signed, mul_ready; - assign mul_ready = 1; + word mul_a, mul_b, mul_c_hi, mul_c_lo, mul_q_hi, mul_q_lo; + psr_flags mul_flags; + + core_mul mult + ( + .a(mul_a), + .b(mul_b), + .c_hi(mul_c_hi), + .c_lo(mul_c_lo), + .long_mul(mul_long), + .add(mul_add), + .sig(mul_signed), + .start(mul), + .q_hi(mul_q_hi), + .q_lo(mul_q_lo), + .n(mul_flags.n), + .z(mul_flags.z), + .ready(mul_ready), + .* + ); ptr data_addr; logic data_start, data_write, data_ready, insn_ready; diff --git a/rtl/core/mul.sv b/rtl/core/mul.sv index 4b0d149..616905f 100644 --- a/rtl/core/mul.sv +++ b/rtl/core/mul.sv @@ -1,141 +1,61 @@ -module core_mul -#(parameter U=32) -( // realiza la operación a * b + c = q - input logic[U - 1:0] a, // primer sumando - b, // segundo sumando - input logic[U - 1:0] c_hi, // parte más significativa de c - c_lo, // parte menos significativa de c - input logic c_size, // 1 si c es de 2 words, cualquier otro valor si c es de 1 word - clk, // clock, ya que es una máquina de estados - rst, // reset - add, // 1 si c se suma - sig, // 1 si a y b son signed - q_size, // 1 si q es de 2 words, cualquier otro valor si es de 1 word - start, // 1 indica que se inicie la multiplicacion +`include "core/uarch.sv" - output logic [U - 1:0] q_hi, // parte más significativa del resultado - output logic [U - 1:0] q_lo, // parte menos significativa del resultado - output logic [2*U-1:0] result, - output logic n, // no hay C ni V, ya que se dejan unaffected - z, - q_sig, // 1 si q es signed, cualquier otro valor si es unsigned - rdy // 1 cuando la multiplicación está lista - - //*Se asume lo siguiente: - // - Las señales de entrada son constantes desde el instante en el que start es 1 hasta que rdy sea 1 - // - El valor de start puede cambiar durante la multiplicación, pero va a ser ignorado hasta que rdy sea 1 - // - El valor de q es UNPREDICTABLE hasta que rdy sea 1 - // - Las condiciones para iniciar una multiplicación son que rdy sea 1 y start sea 1 - // - rdy solo no es 1 mientras la multiplicación se está realiresultando +// Realiza la operación a * b + c = q +module core_mul +( + input logic clk, // clock, ya que es una máquina de estados + input word a, // primer sumando + b, // segundo sumando + c_hi, // parte más significativa de c + c_lo, // parte menos significativa de c + input logic long_mul, // 1 si c es de 2 words, cualquier otro valor si c es de 1 word + add, // 1 si c se suma + sig, // 1 si a y b son signed + start, // 1 indica que se inicie la multiplicacion + + output word q_hi, // parte más significativa del resultado + q_lo, // parte menos significativa del resultado + output logic n, // no hay C ni V, ya que se dejan unaffected + z, + ready // 1 cuando la multiplicación está lista ); - localparam W = U+1; //U=32 , W=33 - localparam IDLE = 1'b0; - localparam START = 1'b1; - - logic signed [2*W - 1:0] result_ext, next_result, result_temp; //66 - logic next_state, current_state; - logic [1:0] temp, next_temp; //temp es la concatenación de {Q0,Qres} - logic [$clog2(U) - 1:0] count, next_count; - logic [2*W - 1:0] c; //66 - logic [2*W - 1:0] a_ext, b_ext; - logic next_rdy; - - assign a_ext = {{(W+1){sig && a[W-1]}}, a}; //65 - assign b_ext = {{(W+1){sig && b[W-1]}}, b}; + logic wait_state; + dword c, q; + + assign ready = wait_state == {$bits(wait_state){1'b0}}; + assign {q_hi, q_lo} = q; + assign n = long_mul ? q_hi[$bits(q_hi) - 1] : q_lo[$bits(q_lo) - 1]; + assign z = q_lo == 0 && (!long_mul || q_hi == 0); + + dsp_mul ip + ( + .clock0(clk), + .aclr0(0), //TODO + .ena0(start || !ready), + .dataa_0(a), + .datab_0(b), + .chainin(c), + .signa(sig), + .signb(sig), + .result(q) + ); always_comb - if (!add) - c = {(2*W){1'b0}}; - else if (c_size) - c = {2'b0, c_hi, c_lo}; + if(!add) + c = {$bits(c){1'b0}}; + else if(long_mul) + c = {c_hi, c_lo}; else - c = {{(W+1){sig && c_lo[W-1]}}, c_lo}; - - always @ (posedge clk or negedge rst) begin - if(!rst) begin - result_ext <= {(2*W){1'b0}}; - rdy <= 1'b0; - current_state <= 1'b0; - temp <= 2'd0; - count <= {$clog2(U){1'b0}}; - end - else begin - result_ext <= next_result; - rdy <= next_rdy; - current_state <= next_state; - temp <= next_temp; - count <= next_count; - end - end - - always @ (*) begin - unique case(current_state) - IDLE: begin - next_count = {$clog2(U){1'b0}}; - next_rdy = 1'b0; - if(start) begin - next_state = START; - next_temp = {a_ext[0],1'b0}; - next_result = {{(W/2){1'b0}},a_ext}; - end - else begin - next_state = current_state; - next_temp = 2'd0; - next_result = result_ext + c; - end - end - - START: begin - unique case(temp) - 2'b10: result_temp = {result_ext[2*W-1: U]-b_ext, result_ext[U-1:0]}; - 2'b01: result_temp = {result_ext[2*W-1: U]+b_ext, result_ext[U-1:0]}; - default: result_temp = result_ext; - endcase - next_temp = {a_ext[count+1],a_ext[count]}; - next_count = count + 1'b1; - next_result = result_temp >>> 1; - next_rdy = (&count) ? 1'b1 : 1'b0; - next_state = (&count) ? IDLE : current_state; - result = result_ext[2*U-1:0]; - q_hi = result_ext[2*U-1: U]; - q_lo = result_ext[U-1: 0]; - n = result_ext[2*W-1]; - z = (|result_ext) ? 1'b0 : 1'b1; - end - endcase - end - - -endmodule + c = {{$bits(word){sig && c_lo[$bits(c_lo) - 1]}}, c_lo}; - -/* - -module mul_tb(); - - logic clk,rst,start; - logic[7:0]X,Y; - logic[15:0]Z; - logic valid; - - always #5 clk = ~clk; - - core_mul_mul #(.W(8)) inst (.clk(clk),.rst(rst),.start(start),.a(X),.b(Y),.rdy(valid),.result(Z)); + always_ff @(posedge clk) + if(wait_state > {$bits(wait_state){1'b0}}) + wait_state <= wait_state - 1; + else if(start) + wait_state <= 1; initial - $monitor($time,"a=%d, b=%d, ready=%d, Z=%d ",X,Y,valid,Z); - initial - begin - X=255;Y=150;clk=1'b1;rst=1'b0;start=1'b0; - #10 rst = 1'b1; - #10 start = 1'b1; - #10 start = 1'b0; - @valid - #10 X=-80;Y=-10;start = 1'b1; - #10 start = 1'b0; - end -endmodule + wait_state = 0; - -*/ +endmodule diff --git a/rtl/core/uarch.sv b/rtl/core/uarch.sv index b6dfc76..4162272 100644 --- a/rtl/core/uarch.sv +++ b/rtl/core/uarch.sv @@ -8,6 +8,7 @@ typedef logic[3:0] reg_num; typedef logic[2:0] cp_opcode; typedef logic[15:0] reg_list; typedef logic[31:0] word; +typedef logic[63:0] dword; typedef logic[29:0] ptr; `define R14 4'b1110 |
