mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-20 11:57:12 -04:00
Headers updates
This commit is contained in:
parent
538ad537e0
commit
0266ddbd0b
15 changed files with 27 additions and 1791 deletions
2
alu.sv
2
alu.sv
|
@ -19,8 +19,6 @@
|
|||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Arithmetic logic unit of the pipelined processor. //
|
||||
// Reduced in area and ISA (RV32I) for small area //
|
||||
// and power consumption. Based on ALU by Matthias Baer. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -22,9 +22,7 @@
|
|||
// Project Name: zero-riscy //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Execution block: Hosts ALU and MUL unit //
|
||||
// ALU: computes additions/subtractions/comparisons //
|
||||
// MAC: //
|
||||
// Description: Execution block: Hosts ALU and MUL/DIV unit //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
161
mult_fast.sv
161
mult_fast.sv
|
@ -1,161 +0,0 @@
|
|||
// Copyright 2015 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the “License”); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this 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.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Engineer: Matthias Baer - baermatt@student.ethz.ch //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// Andreas Traber - atraber@student.ethz.ch //
|
||||
// //
|
||||
// Design Name: Subword multiplier and MAC //
|
||||
// Project Name: RI5CY //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Advanced MAC unit for PULP. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
`define OP_L 15:0
|
||||
`define OP_H 31:16
|
||||
|
||||
module zeroriscy_multdiv_fast
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
input logic mult_en_i,
|
||||
input logic operator_i,
|
||||
input logic [1:0] signed_mode_i,
|
||||
input logic [31:0] op_a_i,
|
||||
input logic [31:0] op_b_i,
|
||||
|
||||
output logic [31:0] mult_result_o,
|
||||
output logic ready_o
|
||||
);
|
||||
|
||||
enum logic [2:0] { ALBL, ALBH, AHBL, AHBH, FINISH } mult_state_q, mult_state_n;
|
||||
|
||||
logic [33:0] mul_res_ext;
|
||||
logic [34:0] mac_res_ext;
|
||||
logic [33:0] mac_res_q, mac_res_n, mac_res;
|
||||
logic [15:0] mult_op_a;
|
||||
logic [15:0] mult_op_b;
|
||||
logic [33:0] accum;
|
||||
logic sign_a,sign_b, accum_sign, signed_mult;
|
||||
|
||||
always_ff @(posedge clk or negedge rst_n) begin : proc_mult_state_q
|
||||
if(~rst_n) begin
|
||||
mult_state_q <= ALBL;
|
||||
mac_res_q <= '0;
|
||||
end else begin
|
||||
if(mult_en_i) begin
|
||||
mult_state_q <= mult_state_n;
|
||||
mac_res_q <= mac_res_n;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign signed_mult = (signed_mode_i != 2'b00);
|
||||
|
||||
assign mult_result_o = mac_res_q[31:0];
|
||||
|
||||
assign mac_res_ext = $signed({sign_a, mult_op_a})*$signed({sign_b, mult_op_b}) + $signed(accum);
|
||||
assign mac_res = mac_res_ext[33:0];
|
||||
|
||||
always_comb
|
||||
begin : mult_fsm
|
||||
ready_o = 1'b0;
|
||||
mult_op_a = op_a_i[`OP_L];
|
||||
mult_op_b = op_b_i[`OP_L];
|
||||
sign_a = 1'b0;
|
||||
sign_b = 1'b0;
|
||||
accum = mac_res_q;
|
||||
mac_res_n = mac_res;
|
||||
|
||||
unique case (mult_state_q)
|
||||
|
||||
ALBL: begin
|
||||
//al*bl
|
||||
mult_op_a = op_a_i[`OP_L];
|
||||
mult_op_b = op_b_i[`OP_L];
|
||||
sign_a = 1'b0;
|
||||
sign_b = 1'b0;
|
||||
accum = '0;
|
||||
mac_res_n = mac_res;
|
||||
mult_state_n = ALBH;
|
||||
end
|
||||
|
||||
ALBH: begin
|
||||
//al*bh<<16
|
||||
mult_op_a = op_a_i[`OP_L];
|
||||
mult_op_b = op_b_i[`OP_H];
|
||||
sign_a = 1'b0;
|
||||
sign_b = signed_mode_i[1] & op_b_i[31];
|
||||
//result of AL*BL (in mac_res_q) always unsigned with no carry, so carries_q always 00
|
||||
accum = {18'b0,mac_res_q[31:16]};
|
||||
unique case(operator_i)
|
||||
MD_OP_MULL: begin
|
||||
mac_res_n = {2'b0,mac_res[`OP_L],mac_res_q[`OP_L]};
|
||||
end
|
||||
MD_OP_MULH: begin
|
||||
mac_res_n = mac_res;
|
||||
end
|
||||
endcase
|
||||
|
||||
mult_state_n = AHBL;
|
||||
end
|
||||
|
||||
AHBL: begin
|
||||
//ah*bl<<16
|
||||
mult_op_a = op_a_i[`OP_H];
|
||||
mult_op_b = op_b_i[`OP_L];
|
||||
sign_a = signed_mode_i[0] & op_a_i[31];
|
||||
sign_b = 1'b0;
|
||||
unique case(operator_i)
|
||||
MD_OP_MULL: begin
|
||||
accum = {18'b0,mac_res_q[31:16]};
|
||||
mac_res_n = {2'b0,mac_res[15:0],mac_res_q[15:0]};
|
||||
mult_state_n = FINISH;
|
||||
end
|
||||
MD_OP_MULH: begin
|
||||
accum = mac_res_q;
|
||||
mac_res_n = mac_res;
|
||||
mult_state_n = AHBH;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
AHBH: begin
|
||||
//only MD_OP_MULH here
|
||||
//ah*bh
|
||||
mult_op_a = op_a_i[`OP_H];
|
||||
mult_op_b = op_b_i[`OP_H];
|
||||
sign_a = signed_mode_i[0] & op_a_i[31];
|
||||
sign_b = signed_mode_i[1] & op_b_i[31];
|
||||
accum[17:0 ] = mac_res_q[33:16];
|
||||
accum[33:18] = {18{signed_mult & mac_res_q[33]}};
|
||||
//result of AH*BL is not signed only if signed_mode_i == 2'b00
|
||||
mac_res_n = mac_res;
|
||||
mult_state_n = FINISH;
|
||||
end
|
||||
|
||||
FINISH: begin
|
||||
mult_state_n = ALBL;
|
||||
//ready_o must not be a timing critical signal
|
||||
ready_o = 1'b1;
|
||||
end
|
||||
|
||||
default:;
|
||||
endcase // mult_state_q
|
||||
end
|
||||
|
||||
|
||||
endmodule // zeroriscy_mult
|
297
mult_slow.sv
297
mult_slow.sv
|
@ -1,297 +0,0 @@
|
|||
// Copyright 2015 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the “License”); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this 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.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Engineer: Davide Schiavone - pschiavo@iis.ee.ethz.ch //
|
||||
// //
|
||||
// //
|
||||
// Design Name: Multiplier and Division //
|
||||
// Project Name: zero-riscy //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Baugh-Wooley multiplier and Long Division //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
|
||||
module zeroriscy_multdiv_slow
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
input logic multdiv_en_i,
|
||||
input logic [1:0] operator_i,
|
||||
input logic [1:0] signed_mode_i,
|
||||
input logic [31:0] op_a_i,
|
||||
input logic [31:0] op_b_i,
|
||||
input logic [33:0] alu_adder_ext_i,
|
||||
input logic [31:0] alu_adder_i,
|
||||
input logic equal_to_zero,
|
||||
|
||||
output logic [32:0] alu_operand_a_o,
|
||||
output logic [32:0] alu_operand_b_o,
|
||||
output logic [31:0] multdiv_result_o,
|
||||
|
||||
output logic ready_o
|
||||
);
|
||||
|
||||
logic [ 4:0] mult_state_q, mult_state_n;
|
||||
enum logic [2:0] { MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH } curr_state_q;
|
||||
|
||||
logic [32:0] accum_window_q;
|
||||
|
||||
logic [32:0] res_adder_l;
|
||||
logic [32:0] res_adder_h;
|
||||
|
||||
logic [32:0] op_b_shift_q;
|
||||
logic [32:0] op_a_shift_q;
|
||||
logic [32:0] op_a_ext, op_b_ext;
|
||||
logic [32:0] one_shift;
|
||||
logic [32:0] op_a_bw_pp, op_a_bw_last_pp;
|
||||
logic [31:0] b_0;
|
||||
logic sign_a, sign_b;
|
||||
logic [32:0] next_reminder, next_quotient;
|
||||
logic [32:0] op_remainder;
|
||||
logic [31:0] op_numerator_q;
|
||||
logic is_greater_equal;
|
||||
logic div_change_sign, rem_change_sign;
|
||||
|
||||
|
||||
//(accum_window_q + op_a_shift_q)
|
||||
assign res_adder_l = alu_adder_ext_i[32:0];
|
||||
//(accum_window_q + op_a_shift_q)>>1
|
||||
assign res_adder_h = alu_adder_ext_i[33:1];
|
||||
|
||||
always_comb
|
||||
begin
|
||||
|
||||
alu_operand_a_o = accum_window_q;
|
||||
multdiv_result_o = accum_window_q[31:0];
|
||||
|
||||
unique case(operator_i)
|
||||
|
||||
MD_OP_MULL: begin
|
||||
alu_operand_b_o = op_a_bw_pp;
|
||||
end
|
||||
|
||||
MD_OP_MULH: begin
|
||||
if(curr_state_q == MD_LAST)
|
||||
alu_operand_b_o = op_a_bw_last_pp;
|
||||
else
|
||||
alu_operand_b_o = op_a_bw_pp;
|
||||
end
|
||||
default: begin
|
||||
unique case(curr_state_q)
|
||||
MD_IDLE: begin
|
||||
//0 - B = 0 iff B == 0
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~op_b_i, 1'b1};
|
||||
end
|
||||
MD_ABS_A: begin
|
||||
//ABS(A) = 0 - A
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~op_a_i, 1'b1};
|
||||
end
|
||||
MD_ABS_B: begin
|
||||
//ABS(B) = 0 - B
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~op_b_i, 1'b1};
|
||||
end
|
||||
MD_CHANGE_SIGN: begin
|
||||
//ABS(Quotient) = 0 - Quotient
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~accum_window_q[31:0], 1'b1};
|
||||
end
|
||||
default: begin
|
||||
//Division
|
||||
alu_operand_a_o = {accum_window_q[31:0], 1'b1}; //it contains the reminder
|
||||
alu_operand_b_o = {~op_b_shift_q[31:0], 1'b1}; //denominator negated + 1 to do -denominator
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endcase
|
||||
|
||||
end
|
||||
|
||||
/*
|
||||
The adder in the ALU computes alu_operand_a_o + alu_operand_b_o which means
|
||||
Reminder - Divisor. If Reminder - Divisor >= 0, is_greater_equal is equal to 1,
|
||||
the next Reminder is Reminder - Divisor contained in res_adder_h and the
|
||||
Quotient mult_state_q-th bit is set to 1 using the shift register op_b_shift_q.
|
||||
The
|
||||
*/
|
||||
|
||||
always_comb
|
||||
begin
|
||||
if ((accum_window_q[31] ^ op_b_shift_q[31]) == 0)
|
||||
is_greater_equal = (res_adder_h[31] == 0);
|
||||
else
|
||||
is_greater_equal = accum_window_q[31];
|
||||
end
|
||||
|
||||
assign one_shift = {32'b0, 1'b1} << mult_state_q;
|
||||
|
||||
assign next_reminder = is_greater_equal ? res_adder_h : op_remainder;
|
||||
assign next_quotient = is_greater_equal ? op_a_shift_q | one_shift : op_a_shift_q;
|
||||
|
||||
assign b_0 = {32{op_b_shift_q[0]}};
|
||||
|
||||
//build the partial product
|
||||
assign op_a_bw_pp = { ~(op_a_shift_q[32] & op_b_shift_q[0]), op_a_shift_q[31:0] & b_0 };
|
||||
|
||||
assign op_a_bw_last_pp = { op_a_shift_q[32] & op_b_shift_q[0], ~(op_a_shift_q[31:0] & b_0) };
|
||||
|
||||
assign sign_a = op_a_i[31] & signed_mode_i[0];
|
||||
assign sign_b = op_b_i[31] & signed_mode_i[1];
|
||||
|
||||
assign op_a_ext = {sign_a, op_a_i};
|
||||
assign op_b_ext = {sign_b, op_b_i};
|
||||
|
||||
//division
|
||||
assign op_remainder = accum_window_q[32:0];
|
||||
|
||||
assign mult_state_n = mult_state_q - 1;
|
||||
assign div_change_sign = sign_a ^ sign_b;
|
||||
assign rem_change_sign = sign_a;
|
||||
|
||||
always_ff @(posedge clk or negedge rst_n) begin : proc_mult_state_q
|
||||
if(~rst_n) begin
|
||||
mult_state_q <= '0;
|
||||
accum_window_q <= '0;
|
||||
op_b_shift_q <= '0;
|
||||
op_a_shift_q <= '0;
|
||||
curr_state_q <= MD_IDLE;
|
||||
op_numerator_q <= '0;
|
||||
end else begin
|
||||
if(multdiv_en_i) begin
|
||||
unique case(curr_state_q)
|
||||
|
||||
MD_IDLE: begin
|
||||
unique case(operator_i)
|
||||
MD_OP_MULL: begin
|
||||
op_a_shift_q <= op_a_ext << 1;
|
||||
accum_window_q <= { ~(op_a_ext[32] & op_b_i[0]), op_a_ext[31:0] & {32{op_b_i[0]}} };
|
||||
op_b_shift_q <= op_b_ext >> 1;
|
||||
curr_state_q <= MD_COMP;
|
||||
end
|
||||
MD_OP_MULH: begin
|
||||
op_a_shift_q <= op_a_ext;
|
||||
accum_window_q <= { 1'b1, ~(op_a_ext[32] & op_b_i[0]), op_a_ext[31:1] & {31{op_b_i[0]}} };
|
||||
op_b_shift_q <= op_b_ext >> 1;
|
||||
curr_state_q <= MD_COMP;
|
||||
end
|
||||
MD_OP_DIV: begin
|
||||
//Check if the Denominator is 0
|
||||
//quotient for division by 0
|
||||
accum_window_q <= '1;
|
||||
curr_state_q <= equal_to_zero ? MD_FINISH : MD_ABS_A;
|
||||
end
|
||||
default: begin
|
||||
//Check if the Denominator is 0
|
||||
//reminder for division by 0
|
||||
accum_window_q <= op_a_ext;
|
||||
curr_state_q <= equal_to_zero ? MD_FINISH : MD_ABS_A;
|
||||
end
|
||||
endcase
|
||||
mult_state_q <= 5'd31;
|
||||
end
|
||||
|
||||
MD_ABS_A: begin
|
||||
//quotient
|
||||
op_a_shift_q <= '0;
|
||||
//A abs value
|
||||
op_numerator_q <= sign_a ? alu_adder_i : op_a_i;
|
||||
curr_state_q <= MD_ABS_B;
|
||||
end
|
||||
|
||||
MD_ABS_B: begin
|
||||
//reminder
|
||||
accum_window_q <= { 32'h0, op_numerator_q[31]};
|
||||
//B abs value
|
||||
op_b_shift_q <= sign_b ? alu_adder_i : op_b_i;
|
||||
curr_state_q <= MD_COMP;
|
||||
end
|
||||
|
||||
MD_COMP: begin
|
||||
|
||||
mult_state_q <= mult_state_n;
|
||||
|
||||
unique case(operator_i)
|
||||
MD_OP_MULL: begin
|
||||
accum_window_q <= res_adder_l;
|
||||
op_a_shift_q <= op_a_shift_q << 1;
|
||||
op_b_shift_q <= op_b_shift_q >> 1;
|
||||
end
|
||||
MD_OP_MULH: begin
|
||||
accum_window_q <= res_adder_h;
|
||||
op_a_shift_q <= op_a_shift_q;
|
||||
op_b_shift_q <= op_b_shift_q >> 1;
|
||||
end
|
||||
default: begin
|
||||
accum_window_q <= {next_reminder[31:0], op_numerator_q[mult_state_n]};
|
||||
op_a_shift_q <= next_quotient;
|
||||
end
|
||||
endcase
|
||||
|
||||
if(mult_state_q == 5'd1)
|
||||
curr_state_q <= MD_LAST;
|
||||
else
|
||||
curr_state_q <= MD_COMP;
|
||||
end
|
||||
|
||||
MD_LAST: begin
|
||||
|
||||
unique case(operator_i)
|
||||
MD_OP_MULL: begin
|
||||
accum_window_q <= res_adder_l;
|
||||
curr_state_q <= MD_FINISH;
|
||||
end
|
||||
MD_OP_MULH: begin
|
||||
accum_window_q <= res_adder_l;
|
||||
curr_state_q <= MD_FINISH;
|
||||
end
|
||||
MD_OP_DIV: begin
|
||||
//this time we save the quotient in accum_window_q since we do not need anymore the reminder
|
||||
accum_window_q <= next_quotient;
|
||||
curr_state_q <= MD_CHANGE_SIGN;
|
||||
end
|
||||
default: begin
|
||||
//this time we do not save the quotient anymore since we need only the reminder
|
||||
accum_window_q <= {1'b0, next_reminder[31:0]};
|
||||
curr_state_q <= MD_CHANGE_SIGN;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
MD_CHANGE_SIGN: begin
|
||||
curr_state_q <= MD_FINISH;
|
||||
if(operator_i == MD_OP_DIV)
|
||||
accum_window_q <= (div_change_sign) ? alu_adder_i : accum_window_q;
|
||||
else
|
||||
accum_window_q <= (rem_change_sign) ? alu_adder_i : accum_window_q;
|
||||
end
|
||||
|
||||
MD_FINISH: begin
|
||||
curr_state_q <= MD_IDLE;
|
||||
end
|
||||
|
||||
default:;
|
||||
endcase // curr_state_q
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
assign ready_o = curr_state_q == MD_FINISH;
|
||||
|
||||
|
||||
endmodule // zeroriscy_mult
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2015 ETH Zurich and University of Bologna.
|
||||
// Copyright 2017 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the “License”); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
|
@ -9,16 +9,14 @@
|
|||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Engineer: Matthias Baer - baermatt@student.ethz.ch //
|
||||
// Engineer: Davide Schiavone - pschiavo@iis.ee.ethz.ch //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// Andreas Traber - atraber@student.ethz.ch //
|
||||
// //
|
||||
// Design Name: Subword multiplier and MAC //
|
||||
// Project Name: RI5CY //
|
||||
// Design Name: Fast Multiplier and Division //
|
||||
// Project Name: zero-riscy //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Advanced MAC unit for PULP. //
|
||||
// Description: 16x16 kernel multiplier and Long Division //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2015 ETH Zurich and University of Bologna.
|
||||
// Copyright 2017 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the “License”); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
|
@ -12,7 +12,7 @@
|
|||
// Engineer: Davide Schiavone - pschiavo@iis.ee.ethz.ch //
|
||||
// //
|
||||
// //
|
||||
// Design Name: Multiplier and Division //
|
||||
// Design Name: Slow Multiplier and Division //
|
||||
// Project Name: zero-riscy //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2015 ETH Zurich and University of Bologna.
|
||||
// Copyright 2017 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the “License”); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
|
|
|
@ -28,33 +28,34 @@
|
|||
|
||||
module zeroriscy_register_file
|
||||
#(
|
||||
parameter ADDR_WIDTH = 5,
|
||||
parameter RV32E = 0,
|
||||
parameter DATA_WIDTH = 32
|
||||
)
|
||||
(
|
||||
// Clock and Reset
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
// Clock and Reset
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
input logic test_en_i,
|
||||
input logic test_en_i,
|
||||
|
||||
//Read port R1
|
||||
input logic [ADDR_WIDTH-1:0] raddr_a_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_a_o,
|
||||
//Read port R1
|
||||
input logic [4:0] raddr_a_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_a_o,
|
||||
|
||||
//Read port R2
|
||||
input logic [ADDR_WIDTH-1:0] raddr_b_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_b_o,
|
||||
//Read port R2
|
||||
input logic [4:0] raddr_b_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_b_o,
|
||||
|
||||
|
||||
// Write port W1
|
||||
input logic [ADDR_WIDTH-1:0] waddr_a_i,
|
||||
input logic [DATA_WIDTH-1:0] wdata_a_i,
|
||||
input logic we_a_i
|
||||
// Write port W1
|
||||
input logic [4:0] waddr_a_i,
|
||||
input logic [DATA_WIDTH-1:0] wdata_a_i,
|
||||
input logic we_a_i
|
||||
|
||||
);
|
||||
|
||||
localparam NUM_WORDS = 2**ADDR_WIDTH;
|
||||
localparam ADDR_WIDTH = RV32E ? 4 : 5;;
|
||||
localparam NUM_WORDS = 2**ADDR_WIDTH;
|
||||
|
||||
logic [NUM_WORDS-1:0][DATA_WIDTH-1:0] rf_reg;
|
||||
logic [NUM_WORDS-1:0] we_a_dec;
|
||||
|
|
|
@ -1,334 +0,0 @@
|
|||
// Copyright 2015 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the “License”); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this 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.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Engineer: Andreas Traber - atraber@iis.ee.ethz.ch //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// //
|
||||
// Design Name: RISC-V Tracer //
|
||||
// Project Name: zero-riscy //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Compares the executed instructions with a golden model //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
// do not import anything if the simchecker is not used
|
||||
// this gets rid of warnings during simulation
|
||||
`ifdef SIMCHECKER
|
||||
import "DPI-C" function chandle riscv_checker_init(input int boot_addr, input int core_id, input int cluster_id);
|
||||
import "DPI-C" function int riscv_checker_step(input chandle cpu, input longint simtime, input int cycle, input logic [31:0] pc, input logic [31:0] instr);
|
||||
import "DPI-C" function void riscv_checker_irq(input chandle cpu, input int irq, input int irq_no);
|
||||
import "DPI-C" function void riscv_checker_mem_access(input chandle cpu, input int we, input logic [31:0] addr, input logic [31:0] data);
|
||||
import "DPI-C" function void riscv_checker_reg_access(input chandle cpu, input logic [31:0] addr, input logic [31:0] data);
|
||||
`endif
|
||||
|
||||
module zeroriscy_simchecker
|
||||
#(
|
||||
parameter REG_ADDR_WIDTH = 5
|
||||
)
|
||||
(
|
||||
// Clock and Reset
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
input logic fetch_enable,
|
||||
input logic [31:0] boot_addr,
|
||||
input logic [3:0] core_id,
|
||||
input logic [5:0] cluster_id,
|
||||
|
||||
input logic [15:0] instr_compressed,
|
||||
input logic if_valid,
|
||||
input logic pc_set,
|
||||
|
||||
input logic [31:0] pc,
|
||||
input logic [31:0] instr,
|
||||
input logic is_compressed,
|
||||
input logic id_valid,
|
||||
input logic is_decoding,
|
||||
input logic is_illegal,
|
||||
input logic is_interrupt,
|
||||
input logic [4:0] irq_no,
|
||||
input logic pipe_flush,
|
||||
|
||||
input logic ex_valid,
|
||||
input logic [(REG_ADDR_WIDTH-1):0] ex_reg_addr,
|
||||
input logic ex_reg_we,
|
||||
input logic [31:0] ex_reg_wdata,
|
||||
|
||||
input logic ex_data_req,
|
||||
input logic ex_data_gnt,
|
||||
input logic ex_data_we,
|
||||
input logic [31:0] ex_data_addr,
|
||||
input logic [31:0] ex_data_wdata,
|
||||
|
||||
input logic lsu_misaligned,
|
||||
input logic wb_bypass,
|
||||
|
||||
input logic wb_valid,
|
||||
input logic [(REG_ADDR_WIDTH-1):0] wb_reg_addr,
|
||||
input logic wb_reg_we,
|
||||
input logic [31:0] wb_reg_wdata,
|
||||
|
||||
input logic wb_data_rvalid,
|
||||
input logic [31:0] wb_data_rdata
|
||||
);
|
||||
|
||||
`ifdef SIMCHECKER
|
||||
// DPI stuff
|
||||
chandle dpi_simdata;
|
||||
|
||||
// SV-only stuff
|
||||
typedef struct {
|
||||
logic [(REG_ADDR_WIDTH-1):0] addr;
|
||||
logic [31:0] value;
|
||||
} reg_t;
|
||||
|
||||
typedef struct {
|
||||
logic [31:0] addr;
|
||||
logic we;
|
||||
logic [ 3:0] be;
|
||||
logic [31:0] wdata;
|
||||
logic [31:0] rdata;
|
||||
} mem_acc_t;
|
||||
|
||||
class instr_trace_t;
|
||||
time simtime;
|
||||
int cycles;
|
||||
logic [31:0] pc;
|
||||
logic [31:0] instr;
|
||||
logic irq;
|
||||
logic [ 4:0] irq_no;
|
||||
logic wb_bypass;
|
||||
reg_t regs_write[$];
|
||||
mem_acc_t mem_access[$];
|
||||
|
||||
function new ();
|
||||
irq = 1'b0;
|
||||
wb_bypass = 1'b1;
|
||||
regs_write = {};
|
||||
mem_access = {};
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
mailbox rdata_stack = new (4);
|
||||
integer rdata_writes = 0;
|
||||
|
||||
integer cycles;
|
||||
|
||||
logic [15:0] instr_compressed_id;
|
||||
logic is_irq_if, is_irq_id;
|
||||
logic [ 4:0] irq_no_id, irq_no_if;
|
||||
|
||||
mailbox instr_ex = new (4);
|
||||
mailbox instr_wb = new (4);
|
||||
|
||||
// simchecker initialization
|
||||
initial
|
||||
begin
|
||||
wait(rst_n == 1'b1);
|
||||
wait(fetch_enable == 1'b1);
|
||||
|
||||
dpi_simdata = riscv_checker_init(boot_addr, core_id, cluster_id);
|
||||
end
|
||||
|
||||
// virtual ID/EX pipeline
|
||||
initial
|
||||
begin
|
||||
instr_trace_t trace;
|
||||
mem_acc_t mem_acc;
|
||||
reg_t reg_write;
|
||||
|
||||
while(1) begin
|
||||
instr_ex.get(trace);
|
||||
|
||||
// wait until we are going to the next stage
|
||||
do begin
|
||||
@(negedge clk);
|
||||
|
||||
reg_write.addr = ex_reg_addr;
|
||||
reg_write.value = ex_reg_wdata;
|
||||
|
||||
if (ex_reg_we)
|
||||
trace.regs_write.push_back(reg_write);
|
||||
|
||||
// look for data accesses and log them
|
||||
if (ex_data_req && ex_data_gnt) begin
|
||||
mem_acc.addr = ex_data_addr;
|
||||
mem_acc.we = ex_data_we;
|
||||
|
||||
if (mem_acc.we)
|
||||
mem_acc.wdata = ex_data_wdata;
|
||||
else
|
||||
mem_acc.wdata = 'x;
|
||||
|
||||
trace.mem_access.push_back(mem_acc);
|
||||
end
|
||||
end while ((!ex_valid || lsu_misaligned) && (!wb_bypass));
|
||||
|
||||
trace.wb_bypass = wb_bypass;
|
||||
|
||||
instr_wb.put(trace);
|
||||
end
|
||||
end
|
||||
|
||||
// virtual EX/WB pipeline
|
||||
initial
|
||||
begin
|
||||
instr_trace_t trace;
|
||||
reg_t reg_write;
|
||||
logic [31:0] tmp_discard;
|
||||
|
||||
while(1) begin
|
||||
instr_wb.get(trace);
|
||||
|
||||
if (!trace.wb_bypass) begin
|
||||
// wait until we are going to the next stage
|
||||
do begin
|
||||
@(negedge clk);
|
||||
#1;
|
||||
|
||||
// pop rdata from stack when there were pending writes
|
||||
while(rdata_stack.num() > 0 && rdata_writes > 0) begin
|
||||
rdata_writes--;
|
||||
rdata_stack.get(tmp_discard);
|
||||
end
|
||||
|
||||
end while (!wb_valid);
|
||||
|
||||
reg_write.addr = wb_reg_addr;
|
||||
reg_write.value = wb_reg_wdata;
|
||||
|
||||
if (wb_reg_we)
|
||||
trace.regs_write.push_back(reg_write);
|
||||
|
||||
// take care of rdata
|
||||
foreach(trace.mem_access[i]) begin
|
||||
if (trace.mem_access[i].we) begin
|
||||
// for writes we don't need to wait for the rdata, so if it has
|
||||
// not appeared yet, we count it and remove it later from out
|
||||
// stack
|
||||
if (rdata_stack.num() > 0)
|
||||
rdata_stack.get(tmp_discard);
|
||||
else
|
||||
rdata_writes++;
|
||||
|
||||
end else begin
|
||||
if (rdata_stack.num() == 0)
|
||||
$warning("rdata stack is empty, but we are waiting for a read");
|
||||
|
||||
if (rdata_writes > 0)
|
||||
$warning("rdata_writes is > 0, but we are waiting for a read");
|
||||
|
||||
rdata_stack.get(trace.mem_access[i].rdata);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// instruction is ready now, all data is inserted
|
||||
foreach(trace.mem_access[i]) begin
|
||||
if (trace.mem_access[i].we)
|
||||
riscv_checker_mem_access(dpi_simdata, trace.mem_access[i].we, trace.mem_access[i].addr, trace.mem_access[i].wdata);
|
||||
else
|
||||
riscv_checker_mem_access(dpi_simdata, trace.mem_access[i].we, trace.mem_access[i].addr, trace.mem_access[i].rdata);
|
||||
end
|
||||
|
||||
foreach(trace.regs_write[i]) begin
|
||||
riscv_checker_reg_access(dpi_simdata, trace.regs_write[i].addr, trace.regs_write[i].value);
|
||||
end
|
||||
|
||||
riscv_checker_irq(dpi_simdata, trace.irq, trace.irq_no);
|
||||
|
||||
if (riscv_checker_step(dpi_simdata, trace.simtime, trace.cycles, trace.pc, trace.instr))
|
||||
$display("%t: Cluster %d, Core %d: Mismatch between simulator and RTL detected", trace.simtime, cluster_id, core_id);
|
||||
end
|
||||
end
|
||||
|
||||
// cycle counter
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0)
|
||||
cycles = 0;
|
||||
else
|
||||
cycles = cycles + 1;
|
||||
end
|
||||
|
||||
// create rdata stack
|
||||
initial
|
||||
begin
|
||||
while(1) begin
|
||||
@(negedge clk);
|
||||
|
||||
if (wb_data_rvalid) begin
|
||||
rdata_stack.put(wb_data_rdata);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk)
|
||||
begin
|
||||
if (pc_set) begin
|
||||
is_irq_if <= is_interrupt;
|
||||
irq_no_if <= irq_no;
|
||||
end else if (if_valid) begin
|
||||
is_irq_if <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk)
|
||||
begin
|
||||
if (if_valid) begin
|
||||
instr_compressed_id <= instr_compressed;
|
||||
is_irq_id <= is_irq_if;
|
||||
irq_no_id <= irq_no_if;
|
||||
end
|
||||
end
|
||||
|
||||
// log execution
|
||||
initial
|
||||
begin
|
||||
instr_trace_t trace;
|
||||
|
||||
while(1) begin
|
||||
@(negedge clk);
|
||||
|
||||
// - special case for WFI because we don't wait for unstalling there
|
||||
// - special case for illegal instructions, since they will not go through
|
||||
// the pipe
|
||||
if ((id_valid && is_decoding) || pipe_flush || (is_decoding && is_illegal))
|
||||
begin
|
||||
trace = new ();
|
||||
|
||||
trace.simtime = $time;
|
||||
trace.cycles = cycles;
|
||||
trace.pc = pc;
|
||||
|
||||
if (is_compressed)
|
||||
trace.instr = {instr_compressed_id, instr_compressed_id};
|
||||
else
|
||||
trace.instr = instr;
|
||||
|
||||
if (is_irq_id) begin
|
||||
trace.irq = 1'b1;
|
||||
trace.irq_no = irq_no_id;
|
||||
end
|
||||
|
||||
instr_ex.put(trace);
|
||||
end
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
endmodule
|
345
tb/serDiv/tb.sv
345
tb/serDiv/tb.sv
|
@ -1,345 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// File : TB for Simple Serial Divider
|
||||
// Ver : 1.0
|
||||
// Date : 15.03.2016
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Description: this is a simple serial divider for signed integers (int32).
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Authors : Michael Schaffner (schaffner@iis.ee.ethz.ch)
|
||||
// Andreas Traber (traber@iis.ee.ethz.ch)
|
||||
//
|
||||
// Copyright (c) 2016 Integrated Systems Laboratory, ETH Zurich
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// tb package
|
||||
module tb;
|
||||
|
||||
// leave this
|
||||
timeunit 1ps;
|
||||
timeprecision 1ps;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MUT signal declarations
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
time C_CLK_HI = 5ns; // set clock high time
|
||||
time C_CLK_LO = 5ns; // set clock low time
|
||||
time C_APPL_DEL = 2ns; // set stimuli application delay
|
||||
time C_ACQ_DEL = 8ns; // set response acquisition delay
|
||||
|
||||
parameter C_WIDTH = 32;
|
||||
parameter C_LOG_WIDTH = 6;
|
||||
|
||||
longint OpA_T, OpA_tmp;
|
||||
longint OpB_T, OpB_tmp;
|
||||
|
||||
logic [C_WIDTH-1:0] OpA_DI;
|
||||
logic [C_WIDTH-1:0] OpB_DI;
|
||||
logic [C_LOG_WIDTH-1:0] OpBShift_DI;
|
||||
logic OpBIsZero_SI;
|
||||
|
||||
logic OpBSign_SI;
|
||||
logic [1:0] OpCode_SI;
|
||||
logic [1:0] OpCode_tmp;
|
||||
|
||||
logic InVld_SI;
|
||||
|
||||
logic OutRdy_SI;
|
||||
logic OutVld_SO;
|
||||
logic [C_WIDTH-1:0] Res_DO;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// TB signal declarations
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
logic Clk_CI, Rst_RBI;
|
||||
logic StimStart_T, StimEnd_T, EndOfSim_T;
|
||||
longint NumStim_T;
|
||||
logic AcqTrig_T;
|
||||
string TestName_T;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// use to ensure proper ATI timing
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
task automatic applWaitCyc(ref logic Clk_C, input int unsigned n);
|
||||
if (n > 0)
|
||||
begin
|
||||
repeat (n) @(posedge(Clk_C));
|
||||
#(C_APPL_DEL);
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic acqWaitCyc(ref logic Clk_C, input int unsigned n);
|
||||
if (n > 0)
|
||||
begin
|
||||
repeat (n) @(posedge(Clk_C));
|
||||
#(C_ACQ_DEL);
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic applWait(ref logic Clk_C, ref logic SigToWaitFor_S);
|
||||
do begin
|
||||
@(posedge(Clk_C));
|
||||
#(C_APPL_DEL);
|
||||
end while(SigToWaitFor_S == 1'b0);
|
||||
endtask
|
||||
|
||||
task automatic acqWait(ref logic Clk_C, ref logic SigToWaitFor_S);
|
||||
do begin
|
||||
@(posedge(Clk_C));
|
||||
#(C_ACQ_DEL);
|
||||
end while(SigToWaitFor_S == 1'b0);
|
||||
endtask
|
||||
|
||||
task automatic acqWait2(ref logic Clk_C, ref logic SigToWaitFor_S, ref logic SigToWaitFor2_S);
|
||||
do begin
|
||||
@(posedge(Clk_C));
|
||||
#(C_ACQ_DEL);
|
||||
end while(SigToWaitFor_S == 1'b0 || SigToWaitFor2_S == 1'b0);
|
||||
endtask
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Clock Process
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
always @*
|
||||
begin
|
||||
do begin
|
||||
Clk_CI = 1; #(C_CLK_HI);
|
||||
Clk_CI = 0; #(C_CLK_LO);
|
||||
end while (EndOfSim_T == 1'b0);
|
||||
// generate one extra cycle to allow response acquisition to complete
|
||||
Clk_CI = 1; #(C_CLK_HI);
|
||||
Clk_CI = 0; #(C_CLK_LO);
|
||||
end
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MUT
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
assign OpBIsZero_SI = ~(|OpB_DI);
|
||||
riscv_alu_div #(.C_WIDTH(C_WIDTH), .C_LOG_WIDTH(C_LOG_WIDTH)) i_mut (.*);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// application process
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
initial // process runs just once
|
||||
begin : p_stim
|
||||
|
||||
longint signed k, j, i;
|
||||
bit ok, randBit;
|
||||
|
||||
StimStart_T = 0;
|
||||
StimEnd_T = 0;
|
||||
NumStim_T = 0;
|
||||
TestName_T = "";
|
||||
AcqTrig_T = 0;
|
||||
|
||||
Rst_RBI = 0;
|
||||
|
||||
OpA_T = 0;
|
||||
OpB_T = 0;
|
||||
|
||||
OpA_DI = 0;
|
||||
OpB_DI = 0;
|
||||
OpBShift_DI = 0;
|
||||
OpBSign_SI = 0;
|
||||
OpCode_SI = 0;
|
||||
InVld_SI = 0;
|
||||
|
||||
applWaitCyc(Clk_CI,100);
|
||||
|
||||
Rst_RBI <= 1'b1;
|
||||
|
||||
applWaitCyc(Clk_CI,100);
|
||||
|
||||
|
||||
$display("stimuli application started");
|
||||
StimStart_T <= 1'b1;
|
||||
applWaitCyc(Clk_CI,100);
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// unsigned division test
|
||||
|
||||
`include "tb_udiv.sv"
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// unsigned modulo test
|
||||
|
||||
`include "tb_urem.sv"
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// signed div test
|
||||
|
||||
`include "tb_div.sv"
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// signed div test
|
||||
|
||||
`include "tb_rem.sv"
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
applWaitCyc(Clk_CI,400);
|
||||
|
||||
StimEnd_T <= 1;
|
||||
$display("stimuli application ended");
|
||||
|
||||
end
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// acquisition process
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
initial // process runs just once
|
||||
begin : p_acq
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// define vars, init...
|
||||
///////////////////////////////////////////////
|
||||
|
||||
longint acqCnt, errCnt, res, act;
|
||||
|
||||
OutRdy_SI = 0;
|
||||
EndOfSim_T = 0;
|
||||
|
||||
acqWait(Clk_CI,StimStart_T);
|
||||
|
||||
$display("response acquisition started");
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// acquisiton and verification
|
||||
///////////////////////////////////////////////
|
||||
|
||||
|
||||
while (1)
|
||||
begin
|
||||
|
||||
// wait for acquisition trigger
|
||||
do begin
|
||||
acqWaitCyc(Clk_CI,1);
|
||||
if (StimEnd_T == 1)
|
||||
begin
|
||||
EndOfSim_T <= 1;
|
||||
$display("response acquisition ended");
|
||||
$finish();
|
||||
end
|
||||
end while(AcqTrig_T == 1'b0);
|
||||
|
||||
acqCnt = 0;
|
||||
|
||||
$display("");
|
||||
$display("------------------------------------------------");
|
||||
$display("%s", TestName_T);
|
||||
$display("------------------------------------------------");
|
||||
$display("");
|
||||
|
||||
$display("checking %00d vectors",NumStim_T);
|
||||
$display("");
|
||||
|
||||
do begin
|
||||
|
||||
OutRdy_SI = 1'b1;
|
||||
|
||||
applWait(Clk_CI, InVld_SI);
|
||||
|
||||
OpCode_tmp = OpCode_SI;
|
||||
OpA_tmp = OpA_T;
|
||||
OpB_tmp = OpB_T;
|
||||
|
||||
//////////////////////////
|
||||
// udiv / udiv
|
||||
if(OpCode_SI[1] == 1'b0)
|
||||
begin
|
||||
|
||||
res = OpA_tmp/OpB_tmp;
|
||||
|
||||
if((OpB_tmp == 0) && (OpCode_SI[0] == 0))
|
||||
begin
|
||||
res = 2**C_WIDTH-1;
|
||||
end
|
||||
else if ((OpB_tmp == 0) && (OpCode_SI[0] == 1'b1))
|
||||
begin
|
||||
res = -1;
|
||||
end
|
||||
else if ((OpA_tmp == -(2**(C_WIDTH-1))) && (OpB_tmp == -1) && (OpCode_SI[0] == 1'b1))
|
||||
begin
|
||||
res = -(2**(C_WIDTH-1));
|
||||
end
|
||||
|
||||
acqWait(Clk_CI, OutVld_SO);
|
||||
|
||||
// interpret result correctly!
|
||||
if (OpCode_tmp[0] == 1'b1)
|
||||
act = $signed(Res_DO);
|
||||
else
|
||||
act = $unsigned(Res_DO);
|
||||
|
||||
if(res !== act)
|
||||
begin
|
||||
$display("vector %d> %d / %d = %d != %d -> error!",acqCnt,OpA_tmp,OpB_tmp,res,act);
|
||||
errCnt++;
|
||||
$stop();
|
||||
end else
|
||||
begin
|
||||
$display("vector %d> %d / %d = %d == %d ",acqCnt,OpA_tmp,OpB_tmp,res,act);
|
||||
end
|
||||
//////////////////////////
|
||||
// rem / urem
|
||||
end else if(OpCode_SI[1] == 1'b1)
|
||||
begin
|
||||
|
||||
res = OpA_tmp % OpB_tmp;
|
||||
|
||||
if((OpB_tmp == 0))
|
||||
begin
|
||||
res = OpA_tmp;
|
||||
end
|
||||
|
||||
acqWait(Clk_CI, OutVld_SO);
|
||||
|
||||
// interpret result correctly!
|
||||
if (OpCode_tmp[0] == 1'b1)
|
||||
act = $signed(Res_DO);
|
||||
else
|
||||
act = $unsigned(Res_DO);
|
||||
|
||||
if(res !== act)
|
||||
begin
|
||||
$display("vector %d> %d mod %d = %d != %d -> error!",acqCnt,OpA_tmp,OpB_tmp, res,act);
|
||||
errCnt++;
|
||||
$stop();
|
||||
end else
|
||||
begin
|
||||
$display("vector %d> %d mod %d = %d == %d ",acqCnt,OpA_tmp,OpB_tmp,res,act);
|
||||
end
|
||||
end
|
||||
// status
|
||||
acqCnt++;
|
||||
end
|
||||
while (acqCnt < NumStim_T);
|
||||
|
||||
|
||||
end
|
||||
///////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
EndOfSim_T <= 1;
|
||||
$display("response acquisition ended");
|
||||
$finish();
|
||||
///////////////////////////////////////////////
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -1,188 +0,0 @@
|
|||
///////////////////////////////////////////////
|
||||
// unsigned division test
|
||||
|
||||
// init
|
||||
NumStim_T = 5+1000;
|
||||
|
||||
TestName_T = "div test";
|
||||
|
||||
AcqTrig_T <= 1;
|
||||
applWaitCyc(Clk_CI,2);
|
||||
AcqTrig_T <= 0;
|
||||
applWaitCyc(Clk_CI,2);
|
||||
|
||||
///////////////////////////////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
OpCode_SI = 1;
|
||||
|
||||
OpA_T = 100;
|
||||
OpB_T = -10;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
///////////////////////////////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
|
||||
OpA_T = -100;
|
||||
OpB_T = -10;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
///////////////////////////////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
|
||||
OpA_T = -100;
|
||||
OpB_T = 0;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
///////////////////////////////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
|
||||
OpA_T = -(2**(C_WIDTH-1));
|
||||
OpB_T = 1;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
///////////////////////////////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
|
||||
OpA_T = -(2**(C_WIDTH-1));
|
||||
OpB_T = -1;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
|
||||
////////////////////
|
||||
// a couple of random stimuli
|
||||
|
||||
for (k = 0; k < 1000; k++) begin
|
||||
|
||||
|
||||
ok = randomize(OpA_T) with {OpA_T>=(-2**(C_WIDTH-1)); OpA_T<=(2**(C_WIDTH-1)-1);};
|
||||
ok = randomize(OpB_T) with {OpB_T>=(-2**(C_WIDTH-1)); OpB_T<=(2**(C_WIDTH-1)-1);};
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
end
|
||||
|
||||
applWaitCyc(Clk_CI, 100);
|
||||
|
||||
///////////////////////////////////////////////
|
|
@ -1,183 +0,0 @@
|
|||
///////////////////////////////////////////////
|
||||
// unsigned division test
|
||||
|
||||
// init
|
||||
NumStim_T = 5+1000;
|
||||
|
||||
TestName_T = "rem test";
|
||||
|
||||
AcqTrig_T <= 1;
|
||||
applWaitCyc(Clk_CI,2);
|
||||
AcqTrig_T <= 0;
|
||||
applWaitCyc(Clk_CI,2);
|
||||
|
||||
///////////////////////////////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
OpCode_SI = 3;
|
||||
|
||||
OpA_T = 100;
|
||||
OpB_T = -10;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
///////////////////////////////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = -100;
|
||||
OpB_T = -10;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
///////////////////////////////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = -100;
|
||||
OpB_T = 0;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
///////////////////////////////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = -(2**(C_WIDTH-1));
|
||||
OpB_T = 1;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
///////////////////////////////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = -(2**(C_WIDTH-1));
|
||||
OpB_T = -1;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
InVld_SI = 0;
|
||||
|
||||
|
||||
////////////////////
|
||||
// a couple of random stimuli
|
||||
|
||||
for (k = 0; k < 1000; k++) begin
|
||||
|
||||
ok = randomize(OpA_T) with {OpA_T>=(-2**(C_WIDTH-1)); OpA_T<=(2**(C_WIDTH-1)-1);};
|
||||
ok = randomize(OpB_T) with {OpB_T>=(-2**(C_WIDTH-1)); OpB_T<=(2**(C_WIDTH-1)-1);};
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpB_DI = OpB_T;
|
||||
OpBSign_SI = (OpB_T & (1<<(C_WIDTH-1))) > 0;
|
||||
|
||||
// depending on the sign of B, we have to calculate the shift differently
|
||||
if (OpBSign_SI == 1'b1)
|
||||
begin
|
||||
OpBShift_DI = 31-$clog2((~OpB_DI)+1);
|
||||
end
|
||||
else begin
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
end
|
||||
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
end
|
||||
|
||||
applWaitCyc(Clk_CI, 100);
|
||||
|
||||
///////////////////////////////////////////////
|
|
@ -1,126 +0,0 @@
|
|||
///////////////////////////////////////////////
|
||||
// unsigned division test
|
||||
|
||||
// init
|
||||
NumStim_T = 6+1000;
|
||||
|
||||
TestName_T = "udiv test";
|
||||
|
||||
AcqTrig_T <= 1;
|
||||
applWaitCyc(Clk_CI,2);
|
||||
AcqTrig_T <= 0;
|
||||
applWaitCyc(Clk_CI,2);
|
||||
|
||||
///////////////////////////////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
OpBSign_SI = 0;
|
||||
OpCode_SI = 0;
|
||||
|
||||
OpA_T = 100;
|
||||
OpB_T = 2;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = 2**32-1;
|
||||
OpB_T = 1;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = 1;
|
||||
OpB_T = 2**32-1;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = 0;
|
||||
OpB_T = 5456;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = 875;
|
||||
OpB_T = 0;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = 0;
|
||||
OpB_T = 0;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
InVld_SI = 0;
|
||||
|
||||
|
||||
////////////////////
|
||||
// a couple of random stimuli
|
||||
|
||||
for (k = 0; k < 1000; k++) begin
|
||||
|
||||
ok = randomize(OpA_T) with {OpA_T>=0; OpA_T<=2**C_WIDTH-1;};
|
||||
ok = randomize(OpB_T) with {OpB_T>=0; OpB_T<=2**C_WIDTH-1;};
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
end
|
||||
|
||||
applWaitCyc(Clk_CI, 100);
|
||||
|
||||
///////////////////////////////////////////////
|
|
@ -1,125 +0,0 @@
|
|||
///////////////////////////////////////////////
|
||||
// unsigned division test
|
||||
|
||||
// init
|
||||
NumStim_T = 6+1000;
|
||||
|
||||
TestName_T = "urem test";
|
||||
|
||||
AcqTrig_T <= 1;
|
||||
applWaitCyc(Clk_CI,2);
|
||||
AcqTrig_T <= 0;
|
||||
applWaitCyc(Clk_CI,2);
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
OpBSign_SI = 0;
|
||||
OpCode_SI = 2;
|
||||
|
||||
OpA_T = 100;
|
||||
OpB_T = 2;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = 2**32-1;
|
||||
OpB_T = 1;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = 1;
|
||||
OpB_T = 2**32-1;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = 0;
|
||||
OpB_T = 5456;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = 875;
|
||||
OpB_T = 0;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
////////////////////
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
OpA_T = 0;
|
||||
OpB_T = 0;
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
InVld_SI = 0;
|
||||
|
||||
////////////////////
|
||||
// a couple of random stimuli
|
||||
|
||||
for (k = 0; k < 1000; k++) begin
|
||||
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
ok = randomize(OpA_T) with {OpA_T>=0; OpA_T<=2**C_WIDTH-1;};
|
||||
ok = randomize(OpB_T) with {OpB_T>=0; OpB_T<=2**C_WIDTH-1;};
|
||||
|
||||
OpA_DI = OpA_T;
|
||||
OpBShift_DI = 32-$clog2(OpB_T+1);
|
||||
OpB_DI = OpB_T << OpBShift_DI;
|
||||
InVld_SI = 1;
|
||||
|
||||
applWaitCyc(Clk_CI,1);
|
||||
applWait(Clk_CI, OutVld_SO);
|
||||
|
||||
InVld_SI = 0;
|
||||
|
||||
end
|
||||
|
||||
applWaitCyc(Clk_CI,100);
|
||||
///////////////////////////////////////////////
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2015 ETH Zurich and University of Bologna.
|
||||
// Copyright 2017 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the “License”); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue