Chapter 2: Verilog Structure
This chapter gives a quick overview of the structural and behavioral elements of Verilog and discusses the time flow and time control statements. Verilog differs from regular programming languages (C, Pascal, ...) in 3 main aspects: (1) simulation time concept, (2) multiple threads, and (3) some basic circuit concepts like network connections and primitive gates. If you know how to program in C and you understand basic digital design then learning Verilog will be easy.
If you have VeriLogger Pro installed on your computer you can copy and paste the following code segments into a text file and simulate the examples.
In Verilog, circuit components are designed inside a module. Modules can contain both structural and behavioral statements. Structural statements represent circuit components like logic gates, counters, and microprocessors. Behavioral level statements are programming statements that have no direct mapping to circuit components like loops, if-then statements, and stimulus vectors which are used to exercise a circuit.
Figure 1 shows an example of a circuit and a test bench module. A module starts with the keyword module followed by an optional module name and an optional port list. The key word endmodule ends a module.
`timescale 1ns / 1ps //create a NAND gate out of an AND and an Invertor module some_logic_component (c, a, b); // declare port signals output c; input a, b; // declare internal wire wire d; //instantiate structural logic gates and a1(d, a, b); //d is output, a and b are inputs not n1(c, d); //c is output, d is input endmodule //test the NAND gate module test_bench; //module with no ports reg A, B; wire C; //instantiate your circuit some_logic_component S1(C, A, B); //Behavioral code block generates stimulus to test circuit initial begin A = 1'b0; B = 1'b0; #50 $display("A = %b, B = %b, Nand output C = %b \n", A, B, C); A = 1'b0; B = 1'b1; #50 $display("A = %b, B = %b, Nand output C = %b \n", A, B, C); A = 1'b1; B = 1'b0; #50 $display("A = %b, B = %b, Nand output C = %b \n", A, B, C); A = 1'b1; B = 1'b1; #50 $display("A = %b, B = %b, Nand output C = %b \n", A, B, C); end endmodule
Figure 1 shows a simple logic circuit and test bench.
2.2 Structural Design with Gate Primitives and the Delay operator
Verilog defines some basic logic gates as part of the language. In Figure 1, module some_logic_component instantiates two gate primitives: the not gate and the and gate. The output of the gate is the first parameter, and the inputs are the rest of the parameters. These primitives are scaleable so you can get multiple input gates just by adding inputs into the parameter list. For example:
nand a1(out1, in1, in2); //2-input NAND gate nand a2(out1, in1, in2, in3, in4, in5); //5-input NAND gate
By default the timing delay for the gate primitives is zero time. You can define the rising delay, falling delay using the #(rise, fall) delay operator. And for tri-state gates you can also define the turn-off delay (transition to high impedance state Z) by using the #(rise, fall, off) delay operator. For example
notif0 #(10,11,27) inv2(c,d,control) //rise=10, fall=11, off=27(not if control=0) nor #(10,11) nor1(c,a,b); //rise=10, fall=11 (nor gate) xnor #(10) xnor1(i,g,h); //rise=10, fall=10 (xnor gate)
Also each of the 3 delays can be defined to have minimum, typical, and a maximum value using the a colon to separate the values like 8:10:12 instead of 10 in the above examples. At run time, the Verilog simulator looks for to see if the +mindelay, +typdelay, or +maxdelay option has been defined so that it will know which of the 3 time values to use. In VeriLogger these options are set using the Project > Project Preferences menu. If none of the options are specified then the typical value is used.
// min:typ:max values defined for the (rise, fall) delays or #(8:10:12, 10:11:13) or1(c,a,b);
The delay operator has one subtle side effect: it swallows narrow input pulses. Normally, the delay operator causes the output response of a gate to be delayed a certain amount of time. However if the input pulse width is shorter then the overall delay of the gate then the change will not be shown on the output.
Here is a list of logic primitives defined for Verilog:
2.3 Structural Design with Assignment Statements
If you have a lot of random logic, the gate primitives of the previous section are tedious to use because all the internal wires must be declared and hooked up correctly. Sometimes it is easier to just describe a circuit using a single Boolean equation. In Verilog, Boolean equations which have similar timing properties as the gate primitives are defined using a continuous assignment statement.
For example, the following code excerpt from Figure 1:
wire d; and a1(d, a, b); not n1(c, d);
can be replaced with one statement:
assign c = !(a && b); //notice that wire d was not used here
Assignments can also be made during the declaration of a wire. In this case the assign keyword is implicitly assumed to be there for example:
wire d; assign d = a || b; //continuous assignment wire d = a || b; //implicit continuous assignment
By default the timing delay for assignment statements is zero time. You can define a propagation delay using the #delay operator just like we did for the gate primitives. The following examples have the exact same timing.
wire c; assign #5 c = a && b; //delay in the continuous assignment wire #5 c = a && b; //delay in the implicit assignment wire #5 c; //delay in the wire declaration assign c = a && b;
To demonstrate the pulse swallowing effect of the delays operator, consider the following senario. In the above examples, if input a changed value at time 10 (and held its value for at least 5 time units), then the output c would change values at time 15. If input a had a value pulse that was shorter then the propagation delay of the assignment then the value on a would not be passed to the output.
The delay operator can also use the full rise, fall, and off delays and each delay can have a minimum:typical: maximum value. The following is a valid line of code.
and #(8:10:12, 10:11:13, 26:27:29) a1(c,a,b); //min:typ:max of (rise,fall,off)
Appendix A defines all of the operators that can be used in an assignment statement.
2.4 Structural Design with using Modules
Verilog supports hierarchical design by allowing modules to instantiate other modules. For example in Figure1 module test_bench instantiates a component S1 of type some_logic_component. The code is reprinted here for convince:
module test_bench; ... some_logic_component S1(C, A, B); //instantiate a some_logic_component module ... endmodule
By default the timing inside a module is controlled by the module itself. However, modules can be defined to have parameterized delays similar to the #(4,5) delay operator used with gate primitives. In the module definition, use the parameter keyword to create delay variables. Parameters can also be used to change other scalar values in the module. When the module is instantiated then you can choose to override the delay values using the #(parameter) notation. For example:
module some_logic_component (c, a, b); ... //some code parameter andDelay = 2; //default delays parameter invDelay = 2; and #andDelay a1(d, a, b); //using parameter delays not #invDelay n1(c, d); endmodule module test_bench; //module with no ports ... some_logic_component #(5,4) S3(E, A, B); //override andDelay=5, invDelay=4 some_logic_component #(5) S2(D, A, B); //override andDelay=5, invDelay=2 some_logic_component S1(C, A, B); //uses default delays .... endmodule
Modules also support a special kind of timing called specify blocks which can be used in conjunction with SDF analyzers. Specify blocks also support continuous setup and hold checking.
2.5 Behavioral Design with Initial and Always blocks
Behavioral code is used to describe circuits at a more abstract level then the structural level statements we have studied. All Behavioral code occurs within either an initial block or in an always block. A module can contain several initial and always blocks. These behavioral blocks contain statements that control simulation time, data flow statements (like if-then and case statements), and blocking and non-blocking statements.
An initial block executes once during a simulation. Initial blocks are usually used to initialize variables and to describe stimulus waveforms which exercise which drive the simulation.
An always block continuously repeats its execution during a simulation. Always blocks usually contain behavioral code that models the actual circuit operation.
During a simulation each always and each initial block begin to execute at time zero. Each block executes concurrently with each structural statement and all the other behavioral blocks. The following example shows a behavioral SRAM model. The initial block sets the memory cells to zero at startup. The always block executes each time there is a change on the write control line, the chip select line, or the address bus. As an exercise, copy and paste this code into a verilog file and write a test bench to exercise the model. If you are using VeriLogger Pro then you can draw a test bench.
//SRAM Model module sram(CSB,WRB,ABUS,DATABUS); input CSB; // active low chip select input WRB; // active low write control input [11:0] ABUS; // 12-bit address bus inout [7:0] DATABUS; // 8-bit data bus //** internal signals reg [7:0] DATABUS_driver; wire [7:0] DATABUS = DATABUS_driver; reg [7:0] ram[0:4095]; // memory cells integer i; initial //initialize all RAM cells to 0 at startup begin DATABUS_driver = 8'bzzzzzzzz; for (i=0; i < 4095; i = i + 1) ram[i] = 0; end always @(CSB or WRB or ABUS) begin if (CSB == 1'b0) begin if (WRB == 1'b0) //Start: latch Data on rising edge of CSB or WRB begin DATABUS_driver <= #10 8'bzzzzzzzz; @(posedge CSB or posedge WRB); $display($time," Writing %m ABUS=%b DATA=%b",ABUS,DATABUS); ram[ABUS] = DATABUS; end if (WRB == 1'b1) //Reading from sram (data becomes valid after 10ns) begin #10 DATABUS_driver = ram[ABUS]; $display($time," Reading %m ABUS=%b DATA=%b",ABUS,DATABUS_driver); end end else //sram unselected, stop driving bus after 10ns begin DATABUS_driver <= #10 8'bzzzzzzzz; end end endmodule
LinksSynaptiCAD provides a free 6 month license for Verilog Simulator