// 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 under the Creative Commons Public Domain. // SPDX-FileCopyrightText: 2012 M W Lund, Atmel Corporation and Jeremy Bennett, Embecosm // SPDX-License-Identifier: CC0-1.0 module t ( 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