Headers updates

This commit is contained in:
Pasquale Davide Schiavone 2017-03-21 17:27:31 +01:00
parent 538ad537e0
commit 0266ddbd0b
15 changed files with 27 additions and 1791 deletions

2
alu.sv
View file

@ -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. //
// //
////////////////////////////////////////////////////////////////////////////////

View file

@ -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 //
// //
////////////////////////////////////////////////////////////////////////////////

View file

@ -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

View file

@ -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

View file

@ -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 //
// //
////////////////////////////////////////////////////////////////////////////////

View file

@ -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 //
// //

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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);
///////////////////////////////////////////////

View file

@ -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);
///////////////////////////////////////////////

View file

@ -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);
///////////////////////////////////////////////

View file

@ -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);
///////////////////////////////////////////////

View file

@ -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