Line 63... |
Line 63... |
|
|
// Multiplier/MAC interface
|
// Multiplier/MAC interface
|
ex_freeze, id_macrc_op, macrc_op, a, b, mac_op, alu_op,
|
ex_freeze, id_macrc_op, macrc_op, a, b, mac_op, alu_op,
|
result, mult_mac_stall,
|
result, mult_mac_stall,
|
|
|
|
// Overflow
|
|
ovforw, ov_we,
|
|
|
// SPR interface
|
// SPR interface
|
spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
|
spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
|
);
|
);
|
|
|
parameter width = `OR1200_OPERAND_WIDTH;
|
parameter width = `OR1200_OPERAND_WIDTH;
|
Line 91... |
Line 94... |
input [width-1:0] b;
|
input [width-1:0] b;
|
input [`OR1200_MACOP_WIDTH-1:0] mac_op;
|
input [`OR1200_MACOP_WIDTH-1:0] mac_op;
|
input [`OR1200_ALUOP_WIDTH-1:0] alu_op;
|
input [`OR1200_ALUOP_WIDTH-1:0] alu_op;
|
output [width-1:0] result;
|
output [width-1:0] result;
|
output mult_mac_stall;
|
output mult_mac_stall;
|
|
output ovforw, ov_we;
|
|
|
//
|
//
|
// SPR interface
|
// SPR interface
|
//
|
//
|
input spr_cs;
|
input spr_cs;
|
Line 153... |
Line 157... |
reg [5:0] div_cntr;
|
reg [5:0] div_cntr;
|
`else
|
`else
|
reg [width-1:0] div_quot_r;
|
reg [width-1:0] div_quot_r;
|
reg [width-1:0] div_quot_generic;
|
reg [width-1:0] div_quot_generic;
|
`endif
|
`endif
|
|
wire div_by_zero;
|
`endif
|
`endif
|
|
reg ovforw, ov_we;
|
|
|
//
|
//
|
// Combinatorial logic
|
// Combinatorial logic
|
//
|
//
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`ifdef OR1200_MULT_IMPLEMENTED
|
Line 187... |
Line 193... |
assign x = (alu_op_sdiv | alu_op_smul) & a[31] ? ~a + 32'b1 :
|
assign x = (alu_op_sdiv | alu_op_smul) & a[31] ? ~a + 32'b1 :
|
alu_op_div | alu_op_mul | (|mac_op) ? a : 32'd0;
|
alu_op_div | alu_op_mul | (|mac_op) ? a : 32'd0;
|
assign y = (alu_op_sdiv | alu_op_smul) & b[31] ? ~b + 32'b1 :
|
assign y = (alu_op_sdiv | alu_op_smul) & b[31] ? ~b + 32'b1 :
|
alu_op_div | alu_op_mul | (|mac_op) ? b : 32'd0;
|
alu_op_div | alu_op_mul | (|mac_op) ? b : 32'd0;
|
|
|
|
assign div_by_zero = !(|b) & alu_op_div;
|
|
|
|
|
// Used to indicate when we should check for new multiply or MAC ops
|
// Used to indicate when we should check for new multiply or MAC ops
|
always @(posedge clk or `OR1200_RST_EVENT rst)
|
always @(posedge clk or `OR1200_RST_EVENT rst)
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
ex_freeze_r <= 1'b1;
|
ex_freeze_r <= 1'b1;
|
else
|
else
|
Line 226... |
Line 235... |
result = mac_r[31:0];
|
result = mac_r[31:0];
|
`endif
|
`endif
|
`else
|
`else
|
result = {width{1'b0}};
|
result = {width{1'b0}};
|
`endif
|
`endif
|
endcase
|
endcase // casez (alu_op)
|
|
|
|
|
|
//
|
|
// Overflow generation
|
|
//
|
|
always @*
|
|
casez(alu_op) // synopsys parallel_case
|
|
`ifdef OR1200_IMPL_OV
|
|
`ifdef OR1200_MULT_IMPLEMENTED
|
|
`OR1200_ALUOP_MUL: begin
|
|
// Actually doing unsigned multiply internally, and then negate on
|
|
// output as appropriate, so if sign bit is set, then is overflow
|
|
ovforw = mul_prod_r[31];
|
|
ov_we = 1;
|
|
end
|
|
`OR1200_ALUOP_MULU : begin
|
|
// Overflow on unsigned multiply is simpler.
|
|
ovforw = mul_prod_r[32];
|
|
ov_we = 1;
|
|
end
|
|
`endif // `ifdef OR1200_MULT_IMPLEMENTED
|
|
`ifdef OR1200_DIV_IMPLEMENTED
|
|
`OR1200_ALUOP_DIVU,
|
|
`OR1200_ALUOP_DIV: begin
|
|
// Overflow on divide by zero
|
|
ovforw = div_by_zero;
|
|
ov_we = 1;
|
|
end
|
|
`endif
|
|
`endif // `ifdef OR1200_IMPL_OV
|
|
default: begin
|
|
ovforw = 0;
|
|
ov_we = 0;
|
|
end
|
|
endcase // casez (alu_op)
|
|
|
|
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`ifdef OR1200_MULT_SERIAL
|
`ifdef OR1200_MULT_SERIAL
|
|
|
always @(`OR1200_RST_EVENT rst or posedge clk)
|
always @(`OR1200_RST_EVENT rst or posedge clk)
|
Line 396... |
Line 441... |
if (rst == `OR1200_RST_VALUE) begin
|
if (rst == `OR1200_RST_VALUE) begin
|
div_quot_r <= 64'h0000_0000_0000_0000;
|
div_quot_r <= 64'h0000_0000_0000_0000;
|
div_free <= 1'b1;
|
div_free <= 1'b1;
|
div_cntr <= 6'b00_0000;
|
div_cntr <= 6'b00_0000;
|
end
|
end
|
|
else if (div_by_zero) begin
|
|
div_quot_r <= 64'h0000_0000_0000_0000;
|
|
div_free <= 1'b1;
|
|
div_cntr <= 6'b00_0000;
|
|
end
|
else if (|div_cntr) begin
|
else if (|div_cntr) begin
|
if (div_tmp[31])
|
if (div_tmp[31])
|
div_quot_r <= {div_quot_r[62:0], 1'b0};
|
div_quot_r <= {div_quot_r[62:0], 1'b0};
|
else
|
else
|
div_quot_r <= {div_tmp[30:0], div_quot_r[31:0], 1'b1};
|
div_quot_r <= {div_tmp[30:0], div_quot_r[31:0], 1'b1};
|