mul unit FIFO trimmed

This commit is contained in:
Eric Matthews 2018-03-29 14:25:06 -07:00
parent cb9ea766e1
commit 9e66c2a331
2 changed files with 45 additions and 119 deletions

View file

@ -1,67 +0,0 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
*/
module mul
#(
parameter CYCLES = 4
)
(
input logic clk,
input logic new_request,
input logic lower,
input logic signa,
input logic signb,
output logic done,
output logic completed_lower,
input logic [31:0] A,
input logic [31:0] B,
output logic [63:0] P
);
logic [32:0] A_r;
logic [32:0] B_r;
logic [65:0] result [0:CYCLES-1];
logic valid [0:CYCLES];
logic mul_type [0:CYCLES];
always_ff @ (posedge clk) begin
A_r <= signed'({A[31] & signa, A});
B_r <= signed'({B[31] & signb, B});
valid[0] <= new_request;
mul_type[0] <= lower;
valid[1] <= valid[0];
mul_type[1] <= mul_type[0];
result[0] <= signed'(A_r) * signed'(B_r);
for (int i = 0; i < CYCLES-1; i = i+1) begin
result[i+1] <= result[i];
valid[i+2] <= valid[i+1];
mul_type[i+2] <= mul_type[i+1];
end
end
assign P = result[CYCLES-1][63:0];
assign done = valid[CYCLES];
assign completed_lower = mul_type[CYCLES];
endmodule

View file

@ -31,65 +31,58 @@ module mul_unit(
unit_writeback_interface.unit mul_wb
);
logic [$clog2(MUL_OUTPUT_BUFFER_DEPTH+1)-1:0] inflight_count;
logic [65:0] result;
logic [1:0] mulh;
logic [1:0] advance;
logic [1:0] valid;
struct packed{
logic [31:0] upper;
logic [31:0] lower;
} mul_result;
logic rs1_signed, rs2_signed;
logic [33:0] rs1_ext, rs2_ext;
logic [33:0] rs1_r, rs2_r;
logic [31:0] result;
logic mul_lower;
logic mul_done_lower;
logic signa, signb;
//implementation
////////////////////////////////////////////////////
assign advance[0] = ~valid[0] | advance[1];
assign advance[1] = mul_wb.accepted | ~valid[1];
fifo_interface #(.DATA_WIDTH(XLEN)) wb_fifo();
always_ff @(posedge clk) begin
if (rst)
inflight_count <= 0;
else if (mul_ex.new_request_dec & ~mul_wb.accepted)
inflight_count <= inflight_count + 1;
else if (~mul_ex.new_request_dec & mul_wb.accepted)
inflight_count <= inflight_count - 1;
always_ff @ (posedge clk) begin
if (rst) begin
valid <= 2'b00;
end
else begin
if (advance[0])
valid[0] <= mul_ex.new_request_dec;
if (advance[1])
valid[1] <= valid[0];
end
end
//Multiply pathway fully pipelined
always_ff @(posedge clk) begin
if (rst)
mul_ex.ready <= 1;
else if (mul_ex.new_request_dec && ~mul_wb.accepted && inflight_count == (MUL_OUTPUT_BUFFER_DEPTH-1))
mul_ex.ready <= 0;
else if (mul_wb.accepted)
mul_ex.ready <= 1;
assign rs1_signed = ~(mul_inputs.op[1:0] == MULHU_fn3[1:0]);
assign rs2_signed = ~mul_inputs.op[1];
assign rs1_ext = {mul_inputs.rs1[31] & rs1_signed, mul_inputs.rs1};
assign rs2_ext = {mul_inputs.rs2[31] & rs2_signed, mul_inputs.rs2};
//Input and output registered Multiply
always_ff @ (posedge clk) begin
if (mul_ex.new_request_dec) begin
rs1_r <= rs1_ext;
rs2_r <= rs2_ext;
mulh[0] <= ~(mul_inputs.op[1:0] == 0);
end
if (advance[1]) begin
result <= (rs1_r) * (rs2_r);
mulh[1] <= mulh[0];
end
end
assign mul_lower = (mul_inputs.op[1:0] == 0);
//Issue/write-back handshaking
////////////////////////////////////////////////////
assign mul_ex.ready = mul_wb.accepted | ~(&valid);
assign signa = ~(mul_inputs.op[1:0] == 2'b11);
assign signb = ~mul_inputs.op[1];
mul #(MUL_CYCLES) multiplier (.*, .A(mul_inputs.rs1), .B(mul_inputs.rs2),
.P(mul_result), .new_request(mul_ex.new_request_dec), .signa(signa), .signb(signb), .lower(mul_lower),
.done(mul_done), .completed_lower(mul_done_lower));
assign result = mul_done_lower ? mul_result.lower : mul_result.upper;
/*********************************
* Output FIFO
*********************************/
taiga_fifo #(
.DATA_WIDTH(XLEN), .FIFO_DEPTH(MUL_OUTPUT_BUFFER_DEPTH), .FIFO_TYPE(NON_MUXED_INPUT_FIFO)
) output_fifo (.fifo(wb_fifo), .*);
assign wb_fifo.data_in = result;
assign wb_fifo.push = mul_done;
assign wb_fifo.pop = mul_wb.accepted;
assign mul_wb.rd = wb_fifo.data_out;
assign mul_wb.done = wb_fifo.early_valid;
assign mul_wb.early_done = 0;//mul_done | (mul_wb.done & ~mul_wb.accepted);
/*********************************************/
assign mul_wb.rd = mulh[1] ? result[63:32] : result[31:0];
assign mul_wb.done = valid[0] | (valid[1] & ~mul_wb.accepted);
assign mul_wb.early_done = 0;
////////////////////////////////////////////////////
endmodule