1// DESCRIPTION: Verilator: System Verilog test of case and if
2//
3// This code instantiates and runs a simple CPU written in System Verilog.
4//
5// This file ONLY is placed into the Public Domain, for any use, without
6// warranty.
7// SPDX-License-Identifier: CC0-1.0
8
9// Contributed 2012 by M W Lund, Atmel Corporation and Jeremy Bennett, Embecosm.
10
11
12module t (/*AUTOARG*/
13   // Inputs
14   clk
15   );
16
17   input clk;
18
19   /*AUTOWIRE*/
20
21   // **************************************************************************
22   // Regs and Wires
23   // **************************************************************************
24
25   reg 	   rst;
26   integer rst_count;
27
28
29   st3_testbench st3_testbench_i (/*AUTOINST*/
30				  // Inputs
31				  .clk			(clk),
32				  .rst			(rst));
33
34   // **************************************************************************
35   // Reset Generation
36   // **************************************************************************
37
38   initial begin
39      rst       = 1'b1;
40      rst_count = 0;
41   end
42
43   always @( posedge clk ) begin
44      if (rst_count < 2) begin
45	 rst_count++;
46      end
47      else begin
48	 rst = 1'b0;
49      end
50   end
51
52   // **************************************************************************
53   // Closing message
54   // **************************************************************************
55
56   final begin
57      $write("*-* All Finished *-*\n");
58   end
59
60endmodule
61
62
63module st3_testbench (/*AUTOARG*/
64   // Inputs
65   clk, rst
66   );
67
68   input  clk;
69   input  rst;
70
71   logic  clk;
72   logic  rst;
73   logic [8*16-1:0] wide_input_bus;
74   logic 	    decrementA;          // 0=Up-counting, 1=down-counting
75   logic 	    dual_countA;         // Advance counter by 2 steps at a time
76   logic 	    cntA_en;             // Enable Counter A
77   logic 	    decrementB;          // 0=Up-counting, 1=down-counting
78   logic 	    dual_countB;         // Advance counter by 2 steps at a time
79   logic 	    cntB_en;             // Enable counter B
80   logic [47:0]     selected_out;
81   integer 	    i;
82
83
84   initial begin
85      decrementA = 1'b0;
86      dual_countA = 1'b0;
87      cntA_en = 1'b1;
88      decrementB = 1'b0;
89      dual_countB = 1'b0;
90      cntB_en = 1'b1;
91      wide_input_bus = {8'hf5,
92                         8'hef,
93                         8'hd5,
94                         8'hc5,
95                         8'hb5,
96                         8'ha5,
97                         8'h95,
98                         8'h85,
99                         8'ha7,
100                         8'ha6,
101                         8'ha5,
102                         8'ha4,
103                         8'ha3,
104                         8'ha2,
105                         8'ha1,
106                         8'ha0};
107      i = 0;
108   end
109
110
111   simple_test_3
112     simple_test_3_i
113       (// Outputs
114	.selected_out                    (selected_out[47:0]),
115	// Inputs
116	.wide_input_bus                  (wide_input_bus[8*16-1:0]),
117	.rst                             (rst),
118	.clk                             (clk),
119	.decrementA                      (decrementA),
120	.dual_countA                     (dual_countA),
121	.cntA_en                         (cntA_en),
122	.decrementB                      (decrementB),
123	.dual_countB                     (dual_countB),
124	.cntB_en                         (cntB_en));
125
126
127   // Logic to print outputs and then finish.
128   always @(posedge clk) begin
129      if (i < 50) begin
130`ifdef TEST_VERBOSE
131	 $display("%x", simple_test_3_i.cntA_reg ,"%x",
132		  simple_test_3_i.cntB_reg ," ", "%x", selected_out);
133`endif
134	 i <= i + 1;
135      end
136      else begin
137	 $finish();
138      end
139   end // always @ (posedge clk)
140
141endmodule
142
143
144// Module testing:
145// - Unique case
146// - Priority case
147// - Unique if
148// - ++, --, =- and =+ operands.
149
150module simple_test_3
151  (input logic [8*16-1:0] wide_input_bus,
152   input logic 	       rst,
153   input logic 	       clk,
154   // Counter A
155   input logic 	       decrementA,  // 0=Up-counting, 1=down-counting
156   input logic 	       dual_countA, // Advance counter by 2 steps at a time
157   input logic 	       cntA_en,     // Enable Counter A
158   // Counter B
159   input logic 	       decrementB,  // 0=Up-counting, 1=down-counting
160   input logic 	       dual_countB, // Advance counter by 2 steps at a time
161   input logic 	       cntB_en,     // Enable counter B
162
163   // Outputs
164   output logic [47:0] selected_out);
165
166   // Declarations
167   logic [3:0] 	       cntA_reg;       // Registered version of cntA
168   logic [3:0] 	       cntB_reg;       // Registered version of cntA
169
170
171   counterA
172     counterA_inst
173       (/*AUTOINST*/
174	// Outputs
175	.cntA_reg			(cntA_reg[3:0]),
176	// Inputs
177	.decrementA			(decrementA),
178	.dual_countA			(dual_countA),
179	.cntA_en			(cntA_en),
180	.clk				(clk),
181	.rst				(rst));
182
183   counterB
184     counterB_inst
185       (/*AUTOINST*/
186	// Outputs
187	.cntB_reg			(cntB_reg[3:0]),
188	// Inputs
189	.decrementB			(decrementB),
190	.dual_countB			(dual_countB),
191	.cntB_en			(cntB_en),
192	.clk				(clk),
193	.rst				(rst));
194
195   simple_test_3a
196     sta
197       (.wide_input_bus        (wide_input_bus),
198	.selector              (cntA_reg),
199	.selected_out          (selected_out[7:0]));
200
201   simple_test_3b
202     stb
203       (.wide_input_bus        (wide_input_bus),
204	.selector              (cntA_reg),
205	.selected_out          (selected_out[15:8]));
206
207   simple_test_3c
208     stc
209       (.wide_input_bus        (wide_input_bus),
210	.selector              (cntB_reg),
211	.selected_out          (selected_out[23:16]));
212
213   simple_test_3d
214     std
215       (.wide_input_bus        (wide_input_bus),
216	.selector              (cntB_reg),
217	.selected_out          (selected_out[31:24]));
218
219   simple_test_3e
220     ste
221       (.wide_input_bus        (wide_input_bus),
222	.selector              (cntB_reg),
223	.selected_out          (selected_out[39:32]));
224
225   simple_test_3f
226     stf
227       (.wide_input_bus        (wide_input_bus),
228	.selector              (cntB_reg),
229	.selected_out          (selected_out[47:40]));
230
231
232endmodule // simple_test_3
233
234
235module counterA
236  (output logic [3:0]          cntA_reg, // Registered version of cntA
237   input logic decrementA,               // 0=Up-counting, 1=down-counting
238   input logic dual_countA,              // Advance counter by 2 steps at a time
239   input logic cntA_en,                  // Enable Counter A
240   input logic clk,                      // Clock
241   input logic rst);                     // Synchronous reset
242
243
244
245   logic [3:0] cntA;                     // combinational count variable.
246
247   // Counter A
248   // Sequential part of counter CntA
249   always_ff @(posedge clk)
250     begin
251	cntA_reg <= cntA;
252     end
253
254   // Combinational part of counter
255   // Had to be split up to test C-style update, as there are no
256   // non-blocking version like -<=
257   always_comb
258     if (rst)
259       cntA = 0;
260     else  begin
261        cntA = cntA_reg;              // Necessary to avoid latch
262        if (cntA_en) begin
263           if (decrementA)
264             if (dual_countA)
265               //cntA = cntA - 2;
266               cntA -= 2;
267             else
268               //cntA = cntA - 1;
269               cntA--;
270           else
271             if (dual_countA)
272               //cntA = cntA + 2;
273               cntA += 2;
274             else
275               //cntA = cntA + 1;
276               cntA++;
277        end // if (cntA_en)
278     end
279endmodule                             // counterA
280
281
282module counterB
283  (output logic [3:0]          cntB_reg, // Registered version of cntA
284   input logic decrementB,               // 0=Up-counting, 1=down-counting
285   input logic dual_countB,              // Advance counter by 2 steps at a time
286   input logic cntB_en,                  // Enable counter B
287   input logic clk,                      // Clock
288   input logic rst);                     // Synchronous reset
289
290   // Counter B - tried to write sequential only, but ended up without
291   // SystemVerilog.
292
293   always_ff @(posedge clk) begin
294      if (rst)
295        cntB_reg <= 0;
296      else
297        if (cntB_en) begin
298           if (decrementB)
299             if (dual_countB)
300               cntB_reg <= cntB_reg - 2;
301             else
302               cntB_reg <= cntB_reg - 1;
303           // Attempts to write in SystemVerilog:
304           else
305             if (dual_countB)
306               cntB_reg <= cntB_reg + 2;
307             else
308               cntB_reg <= cntB_reg + 1;
309           // Attempts to write in SystemVerilog:
310        end
311   end // always_ff @
312endmodule
313
314
315// A multiplexor in terms of look-up
316module simple_test_3a
317  (input logic [8*16-1:0] wide_input_bus,
318   input logic [3:0]  selector,
319   output logic [7:0] selected_out);
320
321
322   always_comb
323     selected_out = {wide_input_bus[selector*8+7],
324                     wide_input_bus[selector*8+6],
325                     wide_input_bus[selector*8+5],
326                     wide_input_bus[selector*8+4],
327                     wide_input_bus[selector*8+3],
328                     wide_input_bus[selector*8+2],
329                     wide_input_bus[selector*8+1],
330                     wide_input_bus[selector*8]};
331
332endmodule // simple_test_3a
333
334
335// A multiplexer in terms of standard case
336module simple_test_3b
337  (input logic [8*16-1:0] wide_input_bus,
338   input logic [3:0]  selector,
339   output logic [7:0] selected_out);
340
341
342   always_comb begin
343      case (selector)
344        4'h0: selected_out = wide_input_bus[  7:  0];
345        4'h1: selected_out = wide_input_bus[ 15:  8];
346        4'h2: selected_out = wide_input_bus[ 23: 16];
347        4'h3: selected_out = wide_input_bus[ 31: 24];
348        4'h4: selected_out = wide_input_bus[ 39: 32];
349        4'h5: selected_out = wide_input_bus[ 47: 40];
350        4'h6: selected_out = wide_input_bus[ 55: 48];
351        4'h7: selected_out = wide_input_bus[ 63: 56];
352        4'h8: selected_out = wide_input_bus[ 71: 64];
353        4'h9: selected_out = wide_input_bus[ 79: 72];
354        4'ha: selected_out = wide_input_bus[ 87: 80];
355        4'hb: selected_out = wide_input_bus[ 95: 88];
356        4'hc: selected_out = wide_input_bus[103: 96];
357        4'hd: selected_out = wide_input_bus[111:104];
358        4'he: selected_out = wide_input_bus[119:112];
359        4'hf: selected_out = wide_input_bus[127:120];
360      endcase // case (selector)
361
362   end
363
364endmodule // simple_test_3b
365
366
367// A multiplexer in terms of unique case
368module simple_test_3c
369  (input logic [8*16-1:0] wide_input_bus,
370   input logic [3:0]  selector,
371   output logic [7:0] selected_out);
372
373
374   always_comb begin
375      unique case (selector)
376        4'h0: selected_out = wide_input_bus[  7:  0];
377        4'h1: selected_out = wide_input_bus[ 15:  8];
378        4'h2: selected_out = wide_input_bus[ 23: 16];
379        4'h3: selected_out = wide_input_bus[ 31: 24];
380        4'h4: selected_out = wide_input_bus[ 39: 32];
381        4'h5: selected_out = wide_input_bus[ 47: 40];
382        4'h6: selected_out = wide_input_bus[ 55: 48];
383        4'h7: selected_out = wide_input_bus[ 63: 56];
384        4'h8: selected_out = wide_input_bus[ 71: 64];
385        4'h9: selected_out = wide_input_bus[ 79: 72];
386        4'ha: selected_out = wide_input_bus[ 87: 80];
387        4'hb: selected_out = wide_input_bus[ 95: 88];
388        4'hc: selected_out = wide_input_bus[103: 96];
389        4'hd: selected_out = wide_input_bus[111:104];
390        4'he: selected_out = wide_input_bus[119:112];
391        4'hf: selected_out = wide_input_bus[127:120];
392      endcase // case (selector)
393
394   end
395
396endmodule // simple_test_3c
397
398
399// A multiplexer in terms of unique if
400module simple_test_3d
401  (input logic [8*16-1:0] wide_input_bus,
402   input logic [3:0]  selector,
403   output logic [7:0] selected_out);
404
405
406   always_comb begin
407      unique if (selector == 4'h0) selected_out = wide_input_bus[  7:  0];
408      else if (selector == 4'h1) selected_out = wide_input_bus[ 15:  8];
409      else if (selector == 4'h2) selected_out = wide_input_bus[ 23: 16];
410      else if (selector == 4'h3) selected_out = wide_input_bus[ 31: 24];
411      else if (selector == 4'h4) selected_out = wide_input_bus[ 39: 32];
412      else if (selector == 4'h5) selected_out = wide_input_bus[ 47: 40];
413      else if (selector == 4'h6) selected_out = wide_input_bus[ 55: 48];
414      else if (selector == 4'h7) selected_out = wide_input_bus[ 63: 56];
415      else if (selector == 4'h8) selected_out = wide_input_bus[ 71: 64];
416      else if (selector == 4'h9) selected_out = wide_input_bus[ 79: 72];
417      else if (selector == 4'ha) selected_out = wide_input_bus[ 87: 80];
418      else if (selector == 4'hb) selected_out = wide_input_bus[ 95: 88];
419      else if (selector == 4'hc) selected_out = wide_input_bus[103: 96];
420      else if (selector == 4'hd) selected_out = wide_input_bus[111:104];
421      else if (selector == 4'he) selected_out = wide_input_bus[119:112];
422      else if (selector == 4'hf) selected_out = wide_input_bus[127:120];
423   end
424
425endmodule // simple_test_3d
426
427
428// Test of priority case
429// Note: This does NOT try to implement the same function as above.
430module simple_test_3e
431  (input logic [8*16-1:0] wide_input_bus,
432   input logic [3:0]  selector,
433   output logic [7:0] selected_out);
434
435
436   always_comb begin
437      priority case (1'b1)
438        selector[0]: selected_out = wide_input_bus[  7:  0]; // Bit 0 has highets priority
439        selector[2]: selected_out = wide_input_bus[ 39: 32]; // Note 2 higher priority than 1
440        selector[1]: selected_out = wide_input_bus[ 23: 16]; // Note 1 lower priority than 2
441        selector[3]: selected_out = wide_input_bus[ 71: 64]; // Bit 3 has lowest priority
442        default:     selected_out = wide_input_bus[127:120]; // for selector = 0.
443      endcase // case (selector)
444
445   end
446
447endmodule // simple_test_3e
448
449
450// Test of "inside"
451// Note: This does NOT try to implement the same function as above.
452// Note: Support for "inside" is a separate Verilator feature request, so is
453//       not used inside a this version of the test.
454module simple_test_3f
455  (input logic [8*16-1:0] wide_input_bus,
456   input logic [3:0]  selector,
457   output logic [7:0] selected_out);
458
459
460   always_comb begin
461/* -----\/----- EXCLUDED -----\/-----
462      if ( selector[3:0] inside { 4'b?00?, 4'b1100})      // Matching 0000, 0001, 1000, 1100, 1001
463	// if ( selector[3:2] inside { 2'b?0, selector[1:0]})
464        selected_out = wide_input_bus[  7:  0];
465      else
466 -----/\----- EXCLUDED -----/\----- */
467      /* verilator lint_off CASEOVERLAP */
468        priority casez (selector[3:0])
469          4'b0?10: selected_out = wide_input_bus[ 15:  8]; // Matching 0010 and 0110
470          4'b0??0: selected_out = wide_input_bus[ 23: 16]; // Overlap: only 0100 remains (0000 in "if" above)
471          4'b0100: selected_out = wide_input_bus[ 31: 24]; // Overlap: Will never occur
472          default: selected_out = wide_input_bus[127:120];   // Remaining 0011,0100,0101,0111,1010,1011,1101,1110,1111
473	endcase // case (selector)
474      /* verilator lint_on CASEOVERLAP */
475   end
476
477endmodule // simple_test_3f
478