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