forked from github/verilator
477 lines
14 KiB
Verilog
477 lines
14 KiB
Verilog
// DESCRIPTION: Verilator: System Verilog test of case and if
|
|
//
|
|
// This code instantiates and runs a simple CPU written in System Verilog.
|
|
//
|
|
// This file ONLY is placed into the Public Domain, for any use, without
|
|
// warranty.
|
|
|
|
// Contributed 2012 by M W Lund, Atmel Corporation and Jeremy Bennett, Embecosm.
|
|
|
|
|
|
module t (/*AUTOARG*/
|
|
// Inputs
|
|
clk
|
|
);
|
|
|
|
input clk;
|
|
|
|
/*AUTOWIRE*/
|
|
|
|
// **************************************************************************
|
|
// Regs and Wires
|
|
// **************************************************************************
|
|
|
|
reg rst;
|
|
integer rst_count;
|
|
|
|
|
|
st3_testbench st3_testbench_i (/*AUTOINST*/
|
|
// Inputs
|
|
.clk (clk),
|
|
.rst (rst));
|
|
|
|
// **************************************************************************
|
|
// Reset Generation
|
|
// **************************************************************************
|
|
|
|
initial begin
|
|
rst = 1'b1;
|
|
rst_count = 0;
|
|
end
|
|
|
|
always @( posedge clk ) begin
|
|
if (rst_count < 2) begin
|
|
rst_count++;
|
|
end
|
|
else begin
|
|
rst = 1'b0;
|
|
end
|
|
end
|
|
|
|
// **************************************************************************
|
|
// Closing message
|
|
// **************************************************************************
|
|
|
|
final begin
|
|
$write("*-* All Finished *-*\n");
|
|
end
|
|
|
|
endmodule
|
|
|
|
|
|
module st3_testbench (/*AUTOARG*/
|
|
// Inputs
|
|
clk, rst
|
|
);
|
|
|
|
input clk;
|
|
input rst;
|
|
|
|
logic clk;
|
|
logic rst;
|
|
logic [8*16-1:0] wide_input_bus;
|
|
logic decrementA; // 0=Up-counting, 1=down-counting
|
|
logic dual_countA; // Advance counter by 2 steps at a time
|
|
logic cntA_en; // Enable Counter A
|
|
logic decrementB; // 0=Up-counting, 1=down-counting
|
|
logic dual_countB; // Advance counter by 2 steps at a time
|
|
logic cntB_en; // Enable counter B
|
|
logic [47:0] selected_out;
|
|
integer i;
|
|
|
|
|
|
initial begin
|
|
decrementA = 1'b0;
|
|
dual_countA = 1'b0;
|
|
cntA_en = 1'b1;
|
|
decrementB = 1'b0;
|
|
dual_countB = 1'b0;
|
|
cntB_en = 1'b1;
|
|
wide_input_bus = {8'hf5,
|
|
8'hef,
|
|
8'hd5,
|
|
8'hc5,
|
|
8'hb5,
|
|
8'ha5,
|
|
8'h95,
|
|
8'h85,
|
|
8'ha7,
|
|
8'ha6,
|
|
8'ha5,
|
|
8'ha4,
|
|
8'ha3,
|
|
8'ha2,
|
|
8'ha1,
|
|
8'ha0};
|
|
i = 0;
|
|
end
|
|
|
|
|
|
simple_test_3
|
|
simple_test_3_i
|
|
(// Outputs
|
|
.selected_out (selected_out[47:0]),
|
|
// Inputs
|
|
.wide_input_bus (wide_input_bus[8*16-1:0]),
|
|
.rst (rst),
|
|
.clk (clk),
|
|
.decrementA (decrementA),
|
|
.dual_countA (dual_countA),
|
|
.cntA_en (cntA_en),
|
|
.decrementB (decrementB),
|
|
.dual_countB (dual_countB),
|
|
.cntB_en (cntB_en));
|
|
|
|
|
|
// Logic to print outputs and then finish.
|
|
always @(posedge clk) begin
|
|
if (i < 50) begin
|
|
`ifdef TEST_VERBOSE
|
|
$display("%x", simple_test_3_i.cntA_reg ,"%x",
|
|
simple_test_3_i.cntB_reg ," ", "%x", selected_out);
|
|
`endif
|
|
i <= i + 1;
|
|
end
|
|
else begin
|
|
$finish();
|
|
end
|
|
end // always @ (posedge clk)
|
|
|
|
endmodule
|
|
|
|
|
|
// Module testing:
|
|
// - Unique case
|
|
// - Priority case
|
|
// - Unique if
|
|
// - ++, --, =- and =+ operands.
|
|
|
|
module simple_test_3
|
|
(input logic [8*16-1:0] wide_input_bus,
|
|
input logic rst,
|
|
input logic clk,
|
|
// Counter A
|
|
input logic decrementA, // 0=Up-counting, 1=down-counting
|
|
input logic dual_countA, // Advance counter by 2 steps at a time
|
|
input logic cntA_en, // Enable Counter A
|
|
// Counter B
|
|
input logic decrementB, // 0=Up-counting, 1=down-counting
|
|
input logic dual_countB, // Advance counter by 2 steps at a time
|
|
input logic cntB_en, // Enable counter B
|
|
|
|
// Outputs
|
|
output logic [47:0] selected_out);
|
|
|
|
// Declarations
|
|
logic [3:0] cntA_reg; // Registered version of cntA
|
|
logic [3:0] cntB_reg; // Registered version of cntA
|
|
|
|
|
|
counterA
|
|
counterA_inst
|
|
(/*AUTOINST*/
|
|
// Outputs
|
|
.cntA_reg (cntA_reg[3:0]),
|
|
// Inputs
|
|
.decrementA (decrementA),
|
|
.dual_countA (dual_countA),
|
|
.cntA_en (cntA_en),
|
|
.clk (clk),
|
|
.rst (rst));
|
|
|
|
counterB
|
|
counterB_inst
|
|
(/*AUTOINST*/
|
|
// Outputs
|
|
.cntB_reg (cntB_reg[3:0]),
|
|
// Inputs
|
|
.decrementB (decrementB),
|
|
.dual_countB (dual_countB),
|
|
.cntB_en (cntB_en),
|
|
.clk (clk),
|
|
.rst (rst));
|
|
|
|
simple_test_3a
|
|
sta
|
|
(.wide_input_bus (wide_input_bus),
|
|
.selector (cntA_reg),
|
|
.selected_out (selected_out[7:0]));
|
|
|
|
simple_test_3b
|
|
stb
|
|
(.wide_input_bus (wide_input_bus),
|
|
.selector (cntA_reg),
|
|
.selected_out (selected_out[15:8]));
|
|
|
|
simple_test_3c
|
|
stc
|
|
(.wide_input_bus (wide_input_bus),
|
|
.selector (cntB_reg),
|
|
.selected_out (selected_out[23:16]));
|
|
|
|
simple_test_3d
|
|
std
|
|
(.wide_input_bus (wide_input_bus),
|
|
.selector (cntB_reg),
|
|
.selected_out (selected_out[31:24]));
|
|
|
|
simple_test_3e
|
|
ste
|
|
(.wide_input_bus (wide_input_bus),
|
|
.selector (cntB_reg),
|
|
.selected_out (selected_out[39:32]));
|
|
|
|
simple_test_3f
|
|
stf
|
|
(.wide_input_bus (wide_input_bus),
|
|
.selector (cntB_reg),
|
|
.selected_out (selected_out[47:40]));
|
|
|
|
|
|
endmodule // simple_test_3
|
|
|
|
|
|
module counterA
|
|
(output logic [3:0] cntA_reg, // Registered version of cntA
|
|
input logic decrementA, // 0=Up-counting, 1=down-counting
|
|
input logic dual_countA, // Advance counter by 2 steps at a time
|
|
input logic cntA_en, // Enable Counter A
|
|
input logic clk, // Clock
|
|
input logic rst); // Synchronous reset
|
|
|
|
|
|
|
|
logic [3:0] cntA; // combinational count variable.
|
|
|
|
// Counter A
|
|
// Sequential part of counter CntA
|
|
always_ff @(posedge clk)
|
|
begin
|
|
cntA_reg <= cntA;
|
|
end
|
|
|
|
// Combinational part of counter
|
|
// Had to be split up to test C-style update, as there are no
|
|
// non-blocking version like -<=
|
|
always_comb
|
|
if (rst)
|
|
cntA = 0;
|
|
else begin
|
|
cntA = cntA_reg; // Necessary to avoid latch
|
|
if (cntA_en) begin
|
|
if (decrementA)
|
|
if (dual_countA)
|
|
//cntA = cntA - 2;
|
|
cntA -= 2;
|
|
else
|
|
//cntA = cntA - 1;
|
|
cntA--;
|
|
else
|
|
if (dual_countA)
|
|
//cntA = cntA + 2;
|
|
cntA += 2;
|
|
else
|
|
//cntA = cntA + 1;
|
|
cntA++;
|
|
end // if (cntA_en)
|
|
end
|
|
endmodule // counterA
|
|
|
|
|
|
module counterB
|
|
(output logic [3:0] cntB_reg, // Registered version of cntA
|
|
input logic decrementB, // 0=Up-counting, 1=down-counting
|
|
input logic dual_countB, // Advance counter by 2 steps at a time
|
|
input logic cntB_en, // Enable counter B
|
|
input logic clk, // Clock
|
|
input logic rst); // Synchronous reset
|
|
|
|
// Counter B - tried to write sequential only, but ended up without
|
|
// SystemVerilog.
|
|
|
|
always_ff @(posedge clk) begin
|
|
if (rst)
|
|
cntB_reg <= 0;
|
|
else
|
|
if (cntB_en) begin
|
|
if (decrementB)
|
|
if (dual_countB)
|
|
cntB_reg <= cntB_reg - 2;
|
|
else
|
|
cntB_reg <= cntB_reg - 1;
|
|
// Attempts to write in SystemVerilog:
|
|
else
|
|
if (dual_countB)
|
|
cntB_reg <= cntB_reg + 2;
|
|
else
|
|
cntB_reg <= cntB_reg + 1;
|
|
// Attempts to write in SystemVerilog:
|
|
end
|
|
end // always_ff @
|
|
endmodule
|
|
|
|
|
|
// A multiplexor in terms of look-up
|
|
module simple_test_3a
|
|
(input logic [8*16-1:0] wide_input_bus,
|
|
input logic [3:0] selector,
|
|
output logic [7:0] selected_out);
|
|
|
|
|
|
always_comb
|
|
selected_out = {wide_input_bus[selector*8+7],
|
|
wide_input_bus[selector*8+6],
|
|
wide_input_bus[selector*8+5],
|
|
wide_input_bus[selector*8+4],
|
|
wide_input_bus[selector*8+3],
|
|
wide_input_bus[selector*8+2],
|
|
wide_input_bus[selector*8+1],
|
|
wide_input_bus[selector*8]};
|
|
|
|
endmodule // simple_test_3a
|
|
|
|
|
|
// A multiplexer in terms of standard case
|
|
module simple_test_3b
|
|
(input logic [8*16-1:0] wide_input_bus,
|
|
input logic [3:0] selector,
|
|
output logic [7:0] selected_out);
|
|
|
|
|
|
always_comb begin
|
|
case (selector)
|
|
4'h0: selected_out = wide_input_bus[ 7: 0];
|
|
4'h1: selected_out = wide_input_bus[ 15: 8];
|
|
4'h2: selected_out = wide_input_bus[ 23: 16];
|
|
4'h3: selected_out = wide_input_bus[ 31: 24];
|
|
4'h4: selected_out = wide_input_bus[ 39: 32];
|
|
4'h5: selected_out = wide_input_bus[ 47: 40];
|
|
4'h6: selected_out = wide_input_bus[ 55: 48];
|
|
4'h7: selected_out = wide_input_bus[ 63: 56];
|
|
4'h8: selected_out = wide_input_bus[ 71: 64];
|
|
4'h9: selected_out = wide_input_bus[ 79: 72];
|
|
4'ha: selected_out = wide_input_bus[ 87: 80];
|
|
4'hb: selected_out = wide_input_bus[ 95: 88];
|
|
4'hc: selected_out = wide_input_bus[103: 96];
|
|
4'hd: selected_out = wide_input_bus[111:104];
|
|
4'he: selected_out = wide_input_bus[119:112];
|
|
4'hf: selected_out = wide_input_bus[127:120];
|
|
endcase // case (selector)
|
|
|
|
end
|
|
|
|
endmodule // simple_test_3b
|
|
|
|
|
|
// A multiplexer in terms of unique case
|
|
module simple_test_3c
|
|
(input logic [8*16-1:0] wide_input_bus,
|
|
input logic [3:0] selector,
|
|
output logic [7:0] selected_out);
|
|
|
|
|
|
always_comb begin
|
|
unique case (selector)
|
|
4'h0: selected_out = wide_input_bus[ 7: 0];
|
|
4'h1: selected_out = wide_input_bus[ 15: 8];
|
|
4'h2: selected_out = wide_input_bus[ 23: 16];
|
|
4'h3: selected_out = wide_input_bus[ 31: 24];
|
|
4'h4: selected_out = wide_input_bus[ 39: 32];
|
|
4'h5: selected_out = wide_input_bus[ 47: 40];
|
|
4'h6: selected_out = wide_input_bus[ 55: 48];
|
|
4'h7: selected_out = wide_input_bus[ 63: 56];
|
|
4'h8: selected_out = wide_input_bus[ 71: 64];
|
|
4'h9: selected_out = wide_input_bus[ 79: 72];
|
|
4'ha: selected_out = wide_input_bus[ 87: 80];
|
|
4'hb: selected_out = wide_input_bus[ 95: 88];
|
|
4'hc: selected_out = wide_input_bus[103: 96];
|
|
4'hd: selected_out = wide_input_bus[111:104];
|
|
4'he: selected_out = wide_input_bus[119:112];
|
|
4'hf: selected_out = wide_input_bus[127:120];
|
|
endcase // case (selector)
|
|
|
|
end
|
|
|
|
endmodule // simple_test_3c
|
|
|
|
|
|
// A multiplexer in terms of unique if
|
|
module simple_test_3d
|
|
(input logic [8*16-1:0] wide_input_bus,
|
|
input logic [3:0] selector,
|
|
output logic [7:0] selected_out);
|
|
|
|
|
|
always_comb begin
|
|
unique if (selector == 4'h0) selected_out = wide_input_bus[ 7: 0];
|
|
else if (selector == 4'h1) selected_out = wide_input_bus[ 15: 8];
|
|
else if (selector == 4'h2) selected_out = wide_input_bus[ 23: 16];
|
|
else if (selector == 4'h3) selected_out = wide_input_bus[ 31: 24];
|
|
else if (selector == 4'h4) selected_out = wide_input_bus[ 39: 32];
|
|
else if (selector == 4'h5) selected_out = wide_input_bus[ 47: 40];
|
|
else if (selector == 4'h6) selected_out = wide_input_bus[ 55: 48];
|
|
else if (selector == 4'h7) selected_out = wide_input_bus[ 63: 56];
|
|
else if (selector == 4'h8) selected_out = wide_input_bus[ 71: 64];
|
|
else if (selector == 4'h9) selected_out = wide_input_bus[ 79: 72];
|
|
else if (selector == 4'ha) selected_out = wide_input_bus[ 87: 80];
|
|
else if (selector == 4'hb) selected_out = wide_input_bus[ 95: 88];
|
|
else if (selector == 4'hc) selected_out = wide_input_bus[103: 96];
|
|
else if (selector == 4'hd) selected_out = wide_input_bus[111:104];
|
|
else if (selector == 4'he) selected_out = wide_input_bus[119:112];
|
|
else if (selector == 4'hf) selected_out = wide_input_bus[127:120];
|
|
end
|
|
|
|
endmodule // simple_test_3d
|
|
|
|
|
|
// Test of priority case
|
|
// Note: This does NOT try to implement the same function as above.
|
|
module simple_test_3e
|
|
(input logic [8*16-1:0] wide_input_bus,
|
|
input logic [3:0] selector,
|
|
output logic [7:0] selected_out);
|
|
|
|
|
|
always_comb begin
|
|
priority case (1'b1)
|
|
selector[0]: selected_out = wide_input_bus[ 7: 0]; // Bit 0 has highets priority
|
|
selector[2]: selected_out = wide_input_bus[ 39: 32]; // Note 2 higher priority than 1
|
|
selector[1]: selected_out = wide_input_bus[ 23: 16]; // Note 1 lower priority than 2
|
|
selector[3]: selected_out = wide_input_bus[ 71: 64]; // Bit 3 has lowest priority
|
|
default: selected_out = wide_input_bus[127:120]; // for selector = 0.
|
|
endcase // case (selector)
|
|
|
|
end
|
|
|
|
endmodule // simple_test_3e
|
|
|
|
|
|
// Test of "inside"
|
|
// Note: This does NOT try to implement the same function as above.
|
|
// Note: Support for "inside" is a separate Verilator feature request, so is
|
|
// not used inside a this version of the test.
|
|
module simple_test_3f
|
|
(input logic [8*16-1:0] wide_input_bus,
|
|
input logic [3:0] selector,
|
|
output logic [7:0] selected_out);
|
|
|
|
|
|
always_comb begin
|
|
/* -----\/----- EXCLUDED -----\/-----
|
|
if ( selector[3:0] inside { 4'b?00?, 4'b1100}) // Matching 0000, 0001, 1000, 1100, 1001
|
|
// if ( selector[3:2] inside { 2'b?0, selector[1:0]})
|
|
selected_out = wide_input_bus[ 7: 0];
|
|
else
|
|
-----/\----- EXCLUDED -----/\----- */
|
|
/* verilator lint_off CASEOVERLAP */
|
|
priority casez (selector[3:0])
|
|
4'b0?10: selected_out = wide_input_bus[ 15: 8]; // Matching 0010 and 0110
|
|
4'b0??0: selected_out = wide_input_bus[ 23: 16]; // Overlap: only 0100 remains (0000 in "if" above)
|
|
4'b0100: selected_out = wide_input_bus[ 31: 24]; // Overlap: Will never occur
|
|
default: selected_out = wide_input_bus[127:120]; // Remaining 0011,0100,0101,0111,1010,1011,1101,1110,1111
|
|
endcase // case (selector)
|
|
/* verilator lint_on CASEOVERLAP */
|
|
end
|
|
|
|
endmodule // simple_test_3f
|