/// Notes and Demos for LSU EE 4702-1 Spring 2001 // Miscellaneous // Sources: Ci: Ciletti, Modeling, synthesis, and rapid prototyping // with the Verilog HDL // LRM: IEEE, Verilog Language Reference Manual /// Contents // // Miscellaneous // Include // Defines define // Removing Definitions (undef) // Testing Definitions (ifdef,else,endif) // Hierarchical Path Names // Parameters // Defparam // Named Ports // Procedural Continuous Assignments // Other compiler directives. (Coming soon.) /// Include // LRM 16.5 // `include "PATHNAME" // // PATHNAME: A valid file or pathname. // // Insert contents of PATHNAME at current location. `include "utility.v" // Not a good use of include. Good uses further below. module x(); handy h1(a,b,y); endmodule /// Defines // LRM 16.3 // Below: define /// Macro definition: `define NAME MACRO_TEXT // // NAME: An identifier // MACRO_TEXT: Almost any text. Text ends at next line not ending with '\' // Cannot start or end in the middle of a comment, operator, keyword, // string, numbers, or identifier. // // Substitute occurrences of `NAME (note back tic) with MACRO_TEXT // Replace occurrences of FOO with BAR. `define FOO BAR // One way of defining a constant. `define BUS_WIDTH 16 // A five-line macro. `define LOTS_OF_STUFF a = 1; \ b = 2; \ c = 3; \ $display("Thank you for using the LOTS_OF_STUFF macro."); \ $display("Have a nice day."); `define EXP a + b module mac_ex(); integer bus_w; integer x, a, b, d; initial begin bus_w = `BUS_WIDTH; x = `EXP + d; end endmodule /// Macro Definition: `define NAME(FORMAL_ARGS) MACRO_TEXT // // NAME: An identifier // FORMAL_ARGS: FORMAL_ARG1, FORMAL_ARG2, ... // Each FORMAL_ARGn is an identifier. // // Macro Use // Compute the minimum. Note parenthesis. `define MIN(a,b) ((a)<(b)?(a):(b)) // Useful in for loops. (See example below.) `define PP(a) a=a+1 /// WARNING: parenthesis around a omitted. Don't let it happen to you! `define DOUBLE(a) 2*a // Not satisfied with current keywords? `define unless(cond) if(!(cond)) `define until(cond) while(!cond) `define infinite_recur `infinite_recur `define CHECK(var) \ if( ^var === 1'bx ) $display("Value undefined"); \ else if( var < 0 ) $display("Too low."); \ else if( var > 100 ) $display("Too high."); module define_examples(); integer foo, bar, i, j; initial begin // The modelsim compiler will hang on the line below. // `infinite_recur // Why parenthesis should be put around macro arguments. $display("Double of 2 is %d, double of 1+1 is %d", `DOUBLE(2), `DOUBLE(1+1)); j = 0; for(i=0; i<10; `PP(i)) begin `unless( i < 9 ) $display("i is %d",i); j = j + i; end bar = 2; foo = `MIN(3,bar); end `ifdef DEBUG always @( foo ) if( foo != bar ) begin $display("It happened!"); $stop; end `endif endmodule /// Removing Definitions // LRM 16.3 // `undef NAME // // NAME: An identifier. // // Remove definition of NAME, if any. `define BREAKFAST eggs // On second thought... `undef BREAKFAST `define BREAKFAST cereal /// An example of poor style that will make debugging difficult. `define TEMPMAC ((a)+(b)/(c)) // Lots of code, some using TEMPMAC `undef TEMPMAC `define TEMPMAC (2*(x)+(y)) /// A better use of `undef. // Use with include to make custom alus. `define WIDTH 64 `define ALUNAME alu_addsub `define OP0(r,a,b) r=a+b; `define OP1(r,a,b) r=a-b; `include "generic_alu.v" `undef ALUNAME `undef OP0 `undef OP1 `define ALUNAME alu_andor `define OP0(r,a,b) r=a&b; `define OP1(r,a,b) r=a|b; `include "generic_alu.v" `undef WIDTH `define WIDTH 32 `undef ALUNAME `undef OP0 `undef OP1 `define ALUNAME alu_minmax `define OP0(r,a,b) if( a < b ) r = a; else r = b; `define OP1(r,a,b) if( a > b ) r = a; else r = b; `include "generic_alu.v" /// Another good use of `undef. // The bean counter testbench description is being used to test 3 different // modules. `define BEANMOD beancount `define BEANTESTMOD beantest `include "beantest.v" `undef BEANMOD `define BEANMOD beancount_s `undef BEANTESTMOD `define BEANTESTMOD beantest_s `include "beantest.v" `undef BEANMOD `define BEANMOD beancount_x `undef BEANTESTMOD `define BEANTESTMOD beantest_x `include "beantest.v" /// Testing Definitions // LRM 16.4 // `ifdef NAME // `else // `endif `define METHOD1 module mymod(somevar); input somevar; `ifdef METHOD1 // some stuff initial begin // METHOD1 code. end always @( somevar ) begin end `else initial begin // METHOD2 code end `endif endmodule /// Hierarchical Path Names // LRM 12.4 // Hierarchical path name is full name of an identifier. module top_mod(); lower_mod lm(); initial $display("avar is %d",lm.avar); initial lm.avar = 3; endmodule module lower_mod(); reg avar; initial avar = 1; endmodule module another_top_mod(); initial $display("avar is %d", top_mod.lm.avar); endmodule module hpn_one(); hpn_two h2a(); hpn_two h2b(); initial $display("States %d %d", h2a.louisiana, h2b.louisiana); initial $display("Fruits: ", h2a.h3a.apple, h2a.h3b.apple, h2b.h3a.apple, h2b.h3b.apple); initial $display("Consumer Electronics: ", h2a.h3a.IBLOCK.tv, h2a.h3b.IBLOCK.tv, h2b.h3a.IBLOCK.tv, h2b.h3b.IBLOCK.tv); initial $display("Pets: ", h2a.h3a.IBLOCK.ABLOCK.cat, h2a.h3b.IBLOCK.ABLOCK.cat, h2b.h3a.IBLOCK.ABLOCK.cat, h2b.h3b.IBLOCK.ABLOCK.cat); endmodule module hpn_two(); reg louisiana, texas; hpn_three h3a(); hpn_three h3b(); endmodule module hpn_three(); reg apple; wire banana; initial begin:IBLOCK reg tv; reg radio; begin:ABLOCK reg cat; reg dog; cat = 111; dog = 222; $display("cat %d, dog %d",cat,dog); end begin:BBLOCK $display("cat %d, dog %d",IBLOCK.ABLOCK.cat,IBLOCK.ABLOCK.dog); end end endmodule /// Parameters // LRM 12.2 // Constants for use in a module. // Module specifies default which can be overridden in instantiation. /// Parameter Declaration // // module FOO(bar); // parameter PARNAME1 = DEFAULT_PAR_VAL1; // parameter PARNAME2 = DEFAULT_PAR_VAL2; // ... // // PARNAME: An identifier. // DEFAULT_PAR_VAL: An expression that evaluates to a constant at compile time. // // Specify default values for parameters. // E.g., DEFAULT_PAR_VAL1 is the default for PARNAME1. /// Specifying Parameter Values in Instantiations // // FOO #(PAR_VAL1,PAR_VAL2,..) MYFOO(MYBAR); // // Specify values used in an instantiation. // E.g., PAR_VAL1 used for parameter 1 (overriding DEFAULT_PAR_VAL1). /// Specifying Parameter Values in Modules // // defparam HIERARCHICAL_PATH_PARAMNAME = VAL; // // Set PARAMNAME in HIERARCHICAL_PATH to VAL module param_examples(); // This is a constant, but be careful when using floating-point numbers. parameter pi = 3.1415926535897932384626433832795028841971693993751058209; // This is okay since compiler can compute expression. parameter seconds_in_a_non_leap_year = 60 * 60 * 24 * 365; // This is okay since compiler can compute expression because pi // is a constant. parameter twopi = 2 * pi; integer i; initial begin // Correct use of a parameter. i = seconds_in_a_non_leap_year / 12; // Line below won't work, can't modify a parameter. // pi = 3; end reg w,v; initial begin w=1; v=2; end // Won't work: w and v are not known at compile time. It doesn't // matter that they are set at start of simulation and don't change. // parameter wplusv = w + v; endmodule /// Using parameters as constants in an ALU module. // Though sub works, the name is not needed throughout this file, // so it should be declared within the module as a parameter. `define sub 1 // Sum works. A parameter could not be used since a+b is not // a constant expression. `define sum a+b module alu_p(result,op,a,b); input op, a, b; output result; parameter add = 0; // parameter sub = 1; parameter pass_a = 2; parameter pass_b = 3; parameter and_op = 4; parameter or_op = 5; // Cannot use a parameter since a-b is not a compile-time constant. // parameter diff = a - b; reg [63:0] result; wire [63:0] a, b; wire [2:0] op; always @( op or a or b ) case( op ) add : result = `sum; `sub : result = a - b; //`sub : result = diff; pass_a : result = a; pass_b : result = b; and_op : result = a & b; or_op : result = a | b; default : result = 0; endcase endmodule /// Using parameters for the width and delay for a multiplexor. module mux_16_4(out,in0,in1,in2,in3,c); input in0, in1, in2, in3, c; output out; parameter width = 16; parameter del = 3; reg [width-1:0] out; wire [width-1:0] in0, in1, in2, in3; wire [1:0] c; always @( in0 or in1 or in2 or in3 or c ) # del case( c ) 0: out = in0; 1: out = in1; 2: out = in2; 3: out = in3; endcase endmodule module use_mux(); reg [1:0] c; reg [7:0] in0_a, in1_a, in2_a, in3_a; reg [15:0] in0_b, in1_b, in2_b, in3_b; wire [7:0] out_a; wire [15:0] out_b; mux_16_4 #(8) mux_a(out_a,in0_a,in1_a,in2_a,in3_a,c); mux_16_4 #(16,7) mux_b(out_b,in0_b,in1_b,in2_b,in3_b,c); mux_16_4 mux_c(out_b,in0_b,in1_b,in2_b,in3_b,c); and #(8) a1(x,a,b); /// Note: The syntax for specifying module parameters and gate delays // are similar, but the semantics (meaning) of a module // parameter is very different than a gate delay. endmodule // Similar to use_mux, but use defparam to specify parameter values. module use_mux2(); reg [1:0] c; reg [7:0] in0_a, in1_a, in2_a, in3_a; reg [15:0] in0_b, in1_b, in2_b, in3_b; wire [7:0] out_a; wire [15:0] out_b; mux_16_4 mux_a(out_a,in0_a,in1_a,in2_a,in3_a,c); mux_16_4 mux_b(out_b,in0_b,in1_b,in2_b,in3_b,c); mux_16_4 mux_c(out_b,in0_b,in1_b,in2_b,in3_b,c); and #(8) a1(x,a,b); endmodule module set_mux2(); defparam use_mux2.mux_a.width = 8; defparam use_mux2.mux_b.width = 16; endmodule /// Named Ports module norad_vending_machine(coffee,hot_chocolate,thermonuclear_war,tea); input coffee,hot_chocolate,tea,thermonuclear_war; // Code removed for security purposes. endmodule module np_example(); reg joe,hc,tea,war; // Ooops. norad_vending_machine mynvm(joe,hc,tea,war); // No problem here: Simulator or other software that // resolves instantiations will detect the port order problem, // saving the world. norad_vending_machine mynvm1(.coffee(joe), .hot_chocolate(hc), .tea(tea), .thermonuclear_war(war)); endmodule /// Procedural Continuous Assignments // LRM 9.3 // assign REG_ASSIGNMENT // deassign REG_NAME // // Used in procedural code. // // assign: Specify that continuous assignment is to start to a reg. // deassign: End a continuous assignment. // force REG_OR_NET_ASSIGNMENT // release RET_OR_NET_NAME // // Used in procedural code. // // force: Specify that continuous assignment to start to a register or net type. // release: End a continuous assignment. // Characteristics // // While a continuous assignment is active ordinary assignment has no effect. // A second continuous assignment replaces the old one. /// These should only be used for special purposes, such as debugging. module pca_example(); integer a, x; wire [31:0] w, w1; assign w1 = x + 1; assign w = x + 1; initial begin a = 10; x = 1; // Set up a continuous assignment to a. Now a will be x + 1. assign a = x + 1; force w1 = x + 1; $display("1 a is %d",a); x = 2; $display("2 a is %d",a); #0; $display("2 after 0 a is %d",a); // The assignment below has no effect. a = 20; #0; $display("20 a is %d",a); deassign a; $display("de a is %d",a); a = 30; $display("30 a is %d",a); release w1; end endmodule /// Other Compiler Directives // Coming soon.