/// EE 4755 - Digital Design Using HDLs // /// Classroom Code Examples // // Covered 21, 23 September 2015 // Simple Sequential Behavioral Code // Counters. // BCD Counter // Time-stamp: <25 September 2015, 15:33:30 CDT, koppel@sky.ece.lsu.edu> ////////////////////////////////////////////////////////////////////////////// module register #( int width = 16 ) ( output logic [width-1:0] val, input wire [width-1:0] data, input wire clk ); always_ff @( posedge clk ) val = data; endmodule module register_en #( int width = 16 ) ( output logic [width-1:0] val, input wire enable, input wire [width-1:0] data, input wire clk ); always_ff @( posedge clk iff enable ) val = data; endmodule module register_sync_reset #( int width = 16 ) ( output logic [width-1:0] val, input wire reset, input wire [width-1:0] data, input wire clk ); always_ff @( posedge clk ) if ( reset ) val = 0; else val = data; endmodule module register_async_reset #( int width = 16 ) ( output logic [width-1:0] val, input wire reset, input wire [width-1:0] data, input wire clk ); always_ff @( posedge clk or posedge reset ) if ( reset ) val = 0; else val = data; endmodule module count #( int bits = 16 ) ( output logic [bits-1:0] c, input wire clk ); initial c = 0; always @( posedge clk ) c++; endmodule module count_reset #( int bits = 16 ) ( output logic [bits-1:0] c, input wire reset, input wire clk ); always_ff @( posedge clk ) if ( reset ) c = 0; else c++; endmodule module count_thd #( int bits = 16 ) ( output logic [bits-1:0] c, output logic over_th, input wire [bits-1:0] threshold, input wire clk ); always_ff @( posedge clk ) begin c++; over_th = c > threshold; end // No delay constraints. // over_th_reg/CLK setup 0 +265 4521 R // count_thd 126 16272 0 16272 <none> (D) // 100 ps delay target // over_th_reg/CLK setup 0 +266 2107 R // count_thd 235 28356 0 28356 <none> (D) endmodule module count_thd_alt2 #( int bits = 16 ) ( output logic [bits-1:0] c, output logic over_th, input wire [bits-1:0] threshold, input wire clk ); always_ff @( posedge clk ) begin over_th = c > threshold; c++; end // No delay constraints. // over_th_reg/CLK setup 0 +277 4272 R // count_thd_alt2 92 15928 0 15928 <none> (D) // 100 ps delay target // c_reg[12]/CLK setup 0 +276 1355 R // count_thd_alt2 191 24492 0 24492 <none> (D) endmodule module count_thd_alt #( int bits = 16 ) ( output logic [bits-1:0] c, output logic over_th, input wire [bits-1:0] threshold, input wire clk ); always_ff @( posedge clk ) c++; always_comb over_th = c > threshold; // No delay constraints. // over_th out port +0 3973 F // count_thd_alt 91 15544 0 15544 <none> (D) // 100 ps delay target // c_reg[15]/CLK setup 0 +276 1340 R // count_thd_alt 189 23160 0 23160 <none> (D) endmodule module count_limit #( int max_val = 9, int bits = $clog2(max_val) ) ( output logic [bits-1:0] c, input wire reset, input wire clk ); always_ff @( posedge clk ) begin if ( reset || c == max_val ) c = 0; else c++; end endmodule `ifdef classroom_live module bcd_count #( int num_digits = 4 ) ( output wire [num_digits-1:0][3:0] count, input wire clk ); count_limit_en #(9) cl0( count[0], 1'b1, clk ); assign en1 = count[0] == 9; count_limit_en #(9) cl1( count[1], en1, clk ); assign en2 = count[1] == 9 && en1; count_limit_en #(9) cl2( count[2], en2, clk ); endmodule `endif module count_limit_en #( int max_val = 9, int bits = $clog2(max_val) ) ( output logic [bits-1:0] c, input wire reset, input wire enable, input wire clk ); always_ff @( posedge clk ) if ( reset ) c = 0; else if ( enable ) begin if ( c == max_val ) c = 0; else c++; end endmodule module bcd_count #( int num_digits = 4 ) ( output wire [num_digits-1:0][3:0] count, input wire reset, input wire clk ); wire nines[num_digits:-1]; assign nines[-1] = 1; for ( genvar d=0; d<num_digits; d++ ) begin count_limit_en #(9) cl0( count[d], reset, nines[d-1], clk ); assign nines[d] = nines[d-1] && count[d] == 9; end endmodule // cadence translate_off module testbench; localparam int width = 4; localparam int num_cyc = 115; logic clk; logic reset; bit done; int cycle; localparam int max_muts = 4; wire [width-1:0] cnt[max_muts]; localparam int num_digits = 3; wire [num_digits-1:0] [3:0] bcd; count #(width) cm1(cnt[0], clk); count_reset #(width) cm2(cnt[1], reset, clk); count_limit #(9) cm3(cnt[2], reset, clk); bcd_count #(num_digits) cm4(bcd,reset,clk); initial begin clk = 0; cycle = 0; done = 0; repeat ( 2 * num_cyc ) #10 cycle += clk++; done = 1; end initial begin reset = 1; @( posedge clk ); @( negedge clk ); reset = 0; do @ ( negedge clk ) begin $write("Cyc %4d cnt %2d %2d %2d %3x\n", cycle, cnt[0], cnt[1], cnt[2], bcd); end while ( !done ); end endmodule // cadence translate_on