/// LSU EE 4755 -- Fall 2018 -- Digital Design / HDL // /// Verilog Notes -- Synthesis of Sequential Logic Examples // /// This file is a supplement to the lecture slides /// Visit http://www.ece.lsu.edu/v/2017/lsli-syn-seq.pdf /// Under Construction /// Contents // /// References // :SV12: IEEE 1800-2012 -- The SystemVerilog Standard // http://standards.ieee.org/getieee/1800/download/1800-2012.pdf // // :BV3: Brown & Vranesic, Fundamentals of Digital Logic with Verilog, 3rd Ed. // The text used in LSU EE 2740. /// Review of Blocking and Non-Block Assignments /// module verilog_stuff(input uwire a); logic [7:0] b, c, d, e; initial begin b = 0; c1 = b; #1; // Nonblocking assignment. lhs <= some_expression + some_other_expression; b <= 1; c2 = b; #2; c3 = b; end initial b = 0; always @( posedge a ) begin c <= b; b <= 1; end always @( posedge a ) begin e <= b; b <= 2; end endmodule /// First Examples of Inferred Registers /// module testc; logic clk; counter myc(count, r, clk); initial clk = 0; always #10 clk = !clk; always @( count ) $write("The counter is now %0d\n", count); endmodule module counter #( int w = 16 ) ( output logic [w-1:0] count, input uwire reset, clk ); always_ff @( posedge clk ) begin count = count + 1; end endmodule module counter #( int w = 16 ) (output logic [w-1:0] count, input uwire reset, clk ); always @( posedge clk ) begin if ( reset ) count = 0; else count++; end endmodule module counter #( int w = 16 ) (output logic [w-1:0] c, input uwire reset, clk ); always_ff @( posedge clk ) begin c = c + 1; if ( reset ) c = 0; end endmodule /// Examples of Describing Common Register Types /// // Behavioral description of d flip-flop. // module d_ff(output logic q, input uwire d, clk); always_ff @( posedge clk ) q <= d; endmodule // d_ff module register #( int width = 16 ) ( output logic [width-1:0] val, input uwire [width-1:0] data, input uwire clk ); always_ff @( posedge clk ) val <= data; endmodule module register_en #( int width = 16 ) ( output logic [width-1:0] val, input uwire enable, input uwire [width-1:0] data, input uwire clk ); always_ff @( posedge clk iff enable ) val <= data; endmodule module register_en #( int width = 16 ) ( output logic [width-1:0] val, input uwire enable, input uwire [width-1:0] data, input uwire clk ); always_ff @( posedge clk ) begin if ( a ) begin if ( enable ) val = data; val = val + 3; if ( e2 ) val = val * 5; end x = val + val2; end always_ff @( posedge clk ) begin x = val + val2; end endmodule module register_sync_reset #( int width = 16 ) ( output logic [width-1:0] val, input uwire reset, input uwire [width-1:0] data, input uwire 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 uwire reset, input uwire [width-1:0] data, input uwire clk ); always_ff @( posedge clk or posedge reset ) if ( reset ) val <= 0; else val <= data; endmodule /// Examples of Counters /// module count #( int bits = 16 ) ( output logic [bits-1:0] c, input uwire clk ); initial c = 0; always @( posedge clk ) c++; endmodule module count_reset #( int bits = 16 ) ( output logic [bits-1:0] c, input uwire reset, input uwire clk ); always_ff @( posedge clk ) if ( reset ) c <= 0; else c <= c + 1; endmodule module count_thd #( int bits = 16 ) ( output logic [bits-1:0] c, output logic over_th, input uwire [bits-1:0] threshold, input uwire clk ); always_ff @( posedge clk ) begin c++; over_th = c > threshold; end endmodule module count_thd_alt2 #( int bits = 16 ) ( output logic [bits-1:0] c, output logic over_th, input uwire [bits-1:0] threshold, input uwire 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 uwire [bits-1:0] threshold, input uwire 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 uwire reset, input uwire 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 uwire [num_digits-1:0][3:0] count, input uwire 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 uwire reset, input uwire enable, input uwire 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 uwire [num_digits-1:0][3:0] count, input uwire reset, input uwire clk ); uwire 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; uwire [width-1:0] cnt[max_muts]; localparam int num_digits = 3; uwire [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