========================================================================== Section 1 Notes ========================================================================== - 1. Linux - 2. Git - 3. Introduction to the Modular Verilog Build System - 4. Verilog Basics: Data Types, Operators, Conditionals - 5. Registered Incrementer: Behavioral Verilog Development & Verification - 6. Sorter: Structural Verilog Development and Verification -------------------------------------------------------------------------- 1. Linux -------------------------------------------------------------------------- * Logging Into amdpool % ssh -X cb535@amdpool.ece.cornell.edu * Setup Script % source setup-ece4750.sh % echo "source setup-ece4750.sh -q" >> ${HOME}/.bashrc * Editors % gedit - file browser - tabs * Quota % quota * Trash % cd ${HOME}/tmp/misc % echo "testing" > testing.txt % trash testing.txt % ls ~/tmp/trash/ * Snapshot % cd ${HOME}/.snapshot -------------------------------------------------------------------------- 2. git -------------------------------------------------------------------------- * Lab admin script % ece4750-lab-admin -h * Start a lab assignment % ece4750-lab-admin list % ece4750-lab-admin start ece4750-tut2-git % ece4750-lab-admin list % ls ${HOME}/ece4750 * Commit some work % cd ${HOME}/ece4750/ece4750-tut2-git % echo "plum" >> fruit.txt % git xadd % git commit -m "added plum to fruit list" % echo "red" >> colors.txt % echo "green" >> colors.txt % echo "blue" >> colors.txt % git add colors.txt % git commit -m "added some colors" * Overall diagram [staff-repos] --> [owner-repo] <--> [ece-repo] <--> [partner-repo] * Collaborate with your partner % whoami cb545 % ece4750-lab-admin add-partner ece4750-tut2-git clt67 % ece4750-lab-admin list-partner ece4750-tut2-git * Have ctorng now join the project % whoami clt67 % ece4750-lab-admin list % ece4750-lab-admin join-owner % ls ${HOME}/ece4750 * Have cbatten make some more changes % whoami cb535 % cd ${HOME}/ece4750/ece4750-tut2-git % echo "plum" >> fruit.txt % git xadd % git commit -m "added a plum to fruit list" % git push * Have ctorng pull these changes and make more changes % whoami clt67 % cd ${HOME}/ece4750/ece4750-tut2-git % git pull % cat fruit.txt % echo "banana" >> fruit.txt % git xadd % git commit -m "added a banana to fruit list" % git push * Have cbatten pull these changes % whoami cb535 % cd ${HOME}/ece4750/ece4750-tut2-git % git pull % cat fruit.txt * GitHub [staff-repos] --> [owner-repo] <--> [ece-repo] <--> [partner-repo] \--> [git-hub ] <--/ - create public repo on GitHub (for labs this needs to be private!) - point local repo to GitHub % git remote rm origin % git remote add origin git@github.com:cbatten/ece4750-tut2-git.git % git push --set-upstream origin master -------------------------------------------------------------------------- 3. Introduction to the Modular Verilog Build System -------------------------------------------------------------------------- * Basic build process % cd ${TUTROOT} % mkdir build % cd build % ../configure % make % make check * Creating new subproject % cd ${TUTDIR} % mkdir ex-types % cd ${TUTROOT}/ex-types % echo " ex_types_deps = ex_types_srcs = ex_types_test_srcs = ex_types_sim_srcs = ex_types_opt_srcs = " > ex-types.mk % cd ${TUTROOT} % echo "subprojs = vc ex-types ex-regincr ex-sorter ex-gcd" > subprojs.mk % cd ${TUTROOT}/build % make % make echo-subprojs * Targets for a single subproject % cd ${TUTROOT}/build % make check-vc % make clean-vc -------------------------------------------------------------------------- 4. Verilog Basics: Data Types, Operators, Conditionals -------------------------------------------------------------------------- * logic 1b - create ex-types-logic-1b.v and add to ex-types.mk `define DISPLAY_OP( expr_ ) \ $display( { " ", `"expr_`", " = %x" }, expr_ ) module top; // logic variables logic a; logic b; logic c; initial begin $display( "" ); $display( " Literals " ); a = 1'b0; $display( " 1'b0 = %x ", a ); a = 1'b1; $display( " 1'b1 = %x ", a ); a = 1'bx; $display( " 1'bx = %x ", a ); a = 1'bz; $display( " 1'bz = %x ", a ); $display( "" ); $display( " Assignment " ); a = 1'b0; b = 1'b1; c = a & b; $display( " 0 & 1 = %x ", c ); $display( "" ); $display( " Logical Operations " ); `DISPLAY_OP( 1'b0 & 1'b0 ); `DISPLAY_OP( 1'b0 & 1'b1 ); `DISPLAY_OP( 1'b1 & 1'b0 ); `DISPLAY_OP( 1'b1 & 1'b1 ); // Also | ^ ~ // Also == != > >= < <= // Also && || ! // Also === !== $display( "" ); $finish; end endmodule * logic 8b module top; logic [7:0] a; logic [7:0] b; logic [7:0] c; initial begin $display( "" ); $display( " Literals " ); a = 8'b0000_0000; $display( " 8'b0000_0000 = %x ", a ); a = 8'b1010_1011; $display( " 8'b1010_1011 = %x ", a ); a = 8'b10xx_0011; $display( " 8'b10xx_0011 = %x ", a ); a = 8'h00; $display( " 8'h00 = %x ", a ); a = 8'hab; $display( " 8'hab = %x ", a ); a = 8'hx3; $display( " 8'hx3 = %x ", a ); a = 8'd0; $display( " 8'd0 = %x ", a ); a = 8'd171; $display( " 8'd171 = %x ", a ); a = 8'd30; $display( " 8'd30 = %x ", a ); $display( "" ); $display( " Logical Operations " ); `DISPLAY_OP( 8'b0101_0011 & 8'b0011_0101 ); `DISPLAY_OP( 8'b0101_0011 | 8'b0011_0101 ); `DISPLAY_OP( 8'b0101_0011 ^ 8'b0011_0101 ); `DISPLAY_OP( ~8'b0101_0011 ); $display( "" ); $display( " Logical Operations w/ X" ); `DISPLAY_OP( 8'b0101_0011 & 8'b0011_xxxx ); `DISPLAY_OP( 8'b0101_0011 | 8'b0011_xxxx ); `DISPLAY_OP( 8'b0101_0011 ^ 8'b0011_xxxx ); `DISPLAY_OP( ~8'b0101_xxxx ); $display( "" ); $display( " Relational Operations " ); `DISPLAY_OP( 8'b0101_0011 == 8'b0011_0101 ); `DISPLAY_OP( 8'b0101_0011 == 8'b0011_xxxx ); $display( "" ); $display( " Special Equality Operations " ); `DISPLAY_OP( 8'b0101_0011 === 8'b0101_0011 ); `DISPLAY_OP( 8'b0101_0011 !== 8'b0101_0011 ); `DISPLAY_OP( 8'b0101_0011 === 8'b0101_xxxx ); `DISPLAY_OP( 8'b0101_xxxx === 8'b0101_xxxx ); `DISPLAY_OP( 8'b0101_0011 !== 8'b0101_xxxx ); `DISPLAY_OP( 8'b0101_xxxx !== 8'b0101_xxxx ); $display( "" ); $finish; end endmodule * enum module top; typedef enum logic [1:0] { STATE_A, STATE_B, STATE_C, STATE_D } state_t; state_t state; initial begin $display( "" ); $display( " Literals " ); state = STATE_A; $display( " STATE_A = %d", state ); state = STATE_B; $display( " STATE_B = %d", state ); state = STATE_C; $display( " STATE_C = %d", state ); state = STATE_D; $display( " STATE_D = %d", state ); $display( "" ); $display( " Comparisons " ); state = STATE_A; $display( " STATE_A == STATE_A = ", state == STATE_A ); $display( " STATE_A == STATE_B = ", state == STATE_B ); $display( "" ); $finish; end endmodule * struct module top; typedef struct packed { logic [3:0] x; logic [3:0] y; logic [7:0] z; } msg_t; msg_t msg_a; initial begin $display( "" ); $display( " Literals " ); msg_a.x = 4'h0; msg_a.y = 4'h1; msg_a.z = 8'h2; $display( " { 0, 1, 2 } = %x", msg_a ); $display( "" ); $display( " Writing/reading fields " ); msg_a.x = 4'h3; msg_a.y = 4'h4; msg_a.z = 8'h5; $display( " msg_a.x = 5'h3, msg_a.x = %x", msg_a.x ); $display( " msg_a.y = 5'h3, msg_a.y = %x", msg_a.y ); $display( " msg_a.z = 5'h3, msg_a.z = %x", msg_a.z ); $display( "" ); $finish; end endmodule * if // What happens if sel is X? sel = 2'd1; if ( sel == 2'd0 ) begin c = 8'h0a; end else if ( sel == 2'd1 ) begin c = 8'h0b; end else if ( sel == 2'd2 ) begin c = 8'h0c; end else if ( sel == 2'd3 ) begin c = 8'h0d; end else begin c = 8'h0e; end // What happens if sel is X? sel = 2'b01; c = ( sel == 2'b00 ) ? 8'h0a : ( sel == 2'b01 ) ? 8'h0b : ( sel == 2'b10 ) ? 8'h0c : ( sel == 2'b11 ) ? 8'h0d : 8'h0e; * case // What happens if sel is X? what if we use X's in select items? sel = 2'b01; case ( sel ) 2'b00 : c = 8'h0a; 2'b01 : c = 8'h0b; 2'b10 : c = 8'h0c; 2'b11 : c = 8'h0d; default : c = 8'h0e; endcase // How does casez work? d = 4'b0100; casez ( d ) 4'b0000 : c = 8'd0; 4'b???1 : c = 8'd1; 4'b??10 : c = 8'd2; 4'b?100 : c = 8'd3; 4'b1000 : c = 8'd4; default : c = 8'hxx; endcase -------------------------------------------------------------------------- 5. Registered Incrementer: Behavioral Verilog Development and Verification -------------------------------------------------------------------------- * Block Diagra of Registered Incrementer - from tutorial document * RTL Behavioral Model of Registered Incrementer `ifndef EX_REGINCR_REG_INCR_V `define EX_REGINCR_REG_INCR_V module ex_regincr_RegIncr ( input logic clk, input logic [7:0] in, output logic [7:0] out ); // Sequential logic logic [7:0] temp_reg; always @( posedge clk ) temp_reg <= in; // Combinational logic logic [7:0] temp_wire; always @(*) temp_wire = temp_reg + 1; // Combinational logic assign out = temp_wire + 1; endmodule `endif /* EX_REGINCR_REG_INCR_V */ * Verifying the Registered Incrementer Using Ad-Hoc Unit Testing - make test pass then make test fail `include "ex-regincr-RegIncr.v" module top; logic clk = 1; always #5 clk = ~clk; logic [7:0] in; logic [7:0] out; ex_regincr_RegIncr reg_incr ( .clk (clk), .in (in), .out (out) ); initial begin #1; in = 8'h00; #10; if ( out != 8'h01 ) begin $display( "ERROR: out, expected = %x, actual = %x", 8'h02, out ); $finish; end in = 8'h13; #10; if ( out != 8'h14 ) begin $display( "ERROR: out, expected = %x, actual = %x", 8'h15, out ); $finish; end in = 8'h27; #10; if ( out != 8'h28 ) begin $display( "ERROR: out, expected = %x, actual = %x", 8'h29, out ); $finish; end $display( "*** PASSED ***" ); $finish; end endmodule * Verifying the Registered Incrementer Using Unit Testing Framework - make test pass then make test fail `include "ex-regincr-RegIncr.v" `include "vc-test.v" module top; `VC_TEST_SUITE_BEGIN( "ex-regincr-RegIncr" ) logic [7:0] t1_in; logic [7:0] t1_out; ex_regincr_RegIncr t1_reg_incr ( .clk (clk), .in (t1_in), .out (t1_out) ); task t1 ( input logic [7:0] in, input logic [7:0] out ); begin t1_in = in; #1; `VC_TEST_NOTE_INPUTS_1( in ); `VC_TEST_NET( t1_out, out ); #9; end endtask `VC_TEST_CASE_BEGIN( 1, "simple" ) begin #1; t1( 8'h00, 8'h?? ); t1( 8'h13, 8'h02 ); t1( 8'h27, 8'h15 ); t1( 8'hxx, 8'h29 ); end `VC_TEST_CASE_END `VC_TEST_SUITE_END endmodule * Behavioral Parameterization for Registered Incrementer module ex_regincr_RegIncrParam #( parameter p_nbits = 8, parameter p_incr_amount = 2 )( input logic clk, input logic [p_nbits-1:0] in, output logic [p_nbits-1:0] out ); // Sequential logic logic [p_nbits-1:0] temp_reg; always @( posedge clk ) temp_reg <= in; // Combinational logic always @(*) out = temp_reg + p_incr_amount; endmodule ex_regincr_RegIncrParam #( .p_nbits (16), .p_incr_amount (4) ) t2_reg_incr ( .clk (clk), .in (t2_in), .out (t2_out) ); * Debugging the Registered Incrementer Using Waveforms % cd ${TUTROOT}/build % gtkwave pex-regincr-RegIncr-test.vcd & -------------------------------------------------------------------------- 6. Sorter: Structural Verilog Development and Verification -------------------------------------------------------------------------- * Block Diagram for Sorter - from tutorial document * Flat Sorter Implementation module ex_sorter_SorterFlat #( parameter p_nbits = 1 )( input logic clk, input logic reset, input logic in_val, input logic [p_nbits-1:0] in0, input logic [p_nbits-1:0] in1, input logic [p_nbits-1:0] in2, input logic [p_nbits-1:0] in3, output logic out_val, output logic [p_nbits-1:0] out0, output logic [p_nbits-1:0] out1, output logic [p_nbits-1:0] out2, output logic [p_nbits-1:0] out3 ); //---------------------------------------------------------------------- // Stage S0->S1 pipeline registers //---------------------------------------------------------------------- logic val_S1; logic [p_nbits-1:0] elm0_S1; logic [p_nbits-1:0] elm1_S1; logic [p_nbits-1:0] elm2_S1; logic [p_nbits-1:0] elm3_S1; always @( posedge clk ) begin val_S1 <= (reset) ? 0 : in_val; elm0_S1 <= in0; elm1_S1 <= in1; elm2_S1 <= in2; elm3_S1 <= in3; end //---------------------------------------------------------------------- // Stage S1 combinational logic //---------------------------------------------------------------------- // Note that we explicitly catch the case where the elements contain // X's and propagate X's appropriately. logic [p_nbits-1:0] elm0_next_S1; logic [p_nbits-1:0] elm1_next_S1; logic [p_nbits-1:0] elm2_next_S1; logic [p_nbits-1:0] elm3_next_S1; always @(*) begin // Sort elms 0 and 1 if ( elm0_S1 <= elm1_S1 ) begin elm0_next_S1 = elm0_S1; elm1_next_S1 = elm1_S1; end else if ( elm0_S1 > elm1_S1 ) begin elm0_next_S1 = elm1_S1; elm1_next_S1 = elm0_S1; end else begin elm0_next_S1 = 'hx; elm1_next_S1 = 'hx; end // Sort elms 2 and 3 if ( elm2_S1 <= elm3_S1 ) begin elm2_next_S1 = elm2_S1; elm3_next_S1 = elm3_S1; end else if ( elm2_S1 > elm3_S1 ) begin elm2_next_S1 = elm3_S1; elm3_next_S1 = elm2_S1; end else begin elm2_next_S1 = 'hx; elm3_next_S1 = 'hx; end end * Visualizing Execution with Line Traces % cd ${TUTDIR} % make ex-sorter-SorterFlat-test % ./ex-sorter-SorterFlat-test +verbose=1 +test-case=1 +trace=1 0: {01,02,03,04}| | | | 1: |{01,02,03,04}| | | 2: | |{01,02,03,04}| | 3: | | |{01,02,03,04}|{01,02,03,04} 4: {04,03,02,01}| | | | 5: |{04,03,02,01}| | | 6: | |{03,04,01,02}| | 7: | | |{01,02,03,04}|{01,02,03,04} 8: {04,02,03,01}| | | | 9: |{04,02,03,01}| | | 10: | |{02,04,01,03}| | 11: | | |{01,03,02,04}|{01,02,03,04} 12: {00,01,00,01}| | | | 13: |{00,01,00,01}| | | 14: | |{00,01,00,01}| | 15: | | |{00,01,00,01}|{00,00,01,01} 16: {04,03,02,01}| | | | 17: |{04,03,02,01}| | | 18: {05,07,06,08}| |{03,04,01,02}| | 19: |{05,07,06,08}| |{01,02,03,04}|{01,02,03,04} 20: | |{05,07,06,08}| | 21: | | |{05,07,06,08}|{05,06,07,08} 22: {04,03,02,01}| | | | 23: {a5,a3,a2,a7}|{04,03,02,01}| | | 24: {05,07,06,08}|{a5,a3,a2,a7}|{03,04,01,02}| | 25: {b0,b1,b0,b1}|{05,07,06,08}|{a3,a5,a2,a7}|{01,02,03,04}|{01,02,03,04} 26: {c7,c1,c2,c6}|{b0,b1,b0,b1}|{05,07,06,08}|{a2,a5,a3,a7}|{a2,a3,a5,a7} 27: |{c7,c1,c2,c6}|{b0,b1,b0,b1}|{05,07,06,08}|{05,06,07,08} 28: | |{c1,c7,c2,c6}|{b0,b1,b0,b1}|{b0,b0,b1,b1} 29: | | |{c1,c6,c2,c7}|{c1,c2,c6,c7} 30: | | | | logic [(`VC_TRACE_NBITS_TO_NCHARS(p_nbits)*4+5)*8-1:0] str; `VC_TRACE_BEGIN begin // Inputs $sformat( str, "{%x,%x,%x,%x}", in0, in1, in2, in3 ); vc_trace.append_val_str( trace_str, in_val, str ); vc_trace.append_str( trace_str, "|" ); // Pipeline stage S1 $sformat( str, "{%x,%x,%x,%x}", elm0_S1, elm1_S1, elm2_S1, elm3_S1 ); vc_trace.append_val_str( trace_str, val_S1, str ); vc_trace.append_str( trace_str, "|" ); ... end `VC_TRACE_END * Structual Sorter Implementation //---------------------------------------------------------------------- // Stage S0->S1 pipeline registers //---------------------------------------------------------------------- logic val_S1; vc_ResetReg#(1) val_S0S1 ( .clk (clk), .reset (reset), .d (in_val), .q (val_S1) ); // This is probably the only place where it might be acceptable to use // positional port binding since (a) it is so common and (b) there are // very few ports to bind. logic [p_nbits-1:0] elm0_S1; logic [p_nbits-1:0] elm1_S1; logic [p_nbits-1:0] elm2_S1; logic [p_nbits-1:0] elm3_S1; vc_Reg#(p_nbits) elm0_S0S1( clk, elm0_S1, in0 ); vc_Reg#(p_nbits) elm1_S0S1( clk, elm1_S1, in1 ); vc_Reg#(p_nbits) elm2_S0S1( clk, elm2_S1, in2 ); vc_Reg#(p_nbits) elm3_S0S1( clk, elm3_S1, in3 ); //---------------------------------------------------------------------- // Stage S1 combinational logic //---------------------------------------------------------------------- logic [p_nbits-1:0] mmuA_out_min_S1; logic [p_nbits-1:0] mmuA_out_max_S1; ex_sorter_MinMaxUnit#(p_nbits) mmuA_S1 ( .in0 (elm0_S1), .in1 (elm1_S1), .out_min (mmuA_out_min_S1), .out_max (mmuA_out_max_S1) ); logic [p_nbits-1:0] mmuB_out_min_S1; logic [p_nbits-1:0] mmuB_out_max_S1; ex_sorter_MinMaxUnit#(p_nbits) mmuB_S1 ( .in0 (elm2_S1), .in1 (elm3_S1), .out_min (mmuB_out_min_S1), .out_max (mmuB_out_max_S1) ); * Verifying the Sorter Using Randomized Testing % cd ${TUTROOT}/build % python ../ex-sorter/ex-sorter-gen-input.py random % make ex-sorter-gen-input_random.py.v % make ex-sorter-gen-input_sorted-fwd.py.v % make ex-sorter-gen-input_sorted-rev.py.v % make ex-sorter-check `VC_TEST_CASE_BEGIN( 2, "random inputs" ) begin #1; t1_reset = 1'b1; #20; t1_reset = 1'b0; `include "ex-sorter-gen-input_random.py.v" end `VC_TEST_CASE_END * Evaluating the Sorter Using a Simulator % cd ${TUTROOT}/build % make ex-sorter-sim-flat % ./ex-sorter-sim-flat +input=random +trace=1 +stats % make ex-sorter-eval