Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
dsd1-10 / dsd-07=Verilog / vlogmsg.pdf
Скачиваний:
79
Добавлен:
05.06.2015
Размер:
276.27 Кб
Скачать

Verilog-XL Modeling Style Guide

2

Modeling Your Hardware (Gate-Level)

This chapter describes how to model your hardware at the gate level.

Instantiating Gates

You declare any of Verilog HDL’s predefined gate types, also called gate primitives, through a process called instantiation. Instantiating a gate is similar to declaring any of Verilog HDL’s other types, except that you can also declare delay and drive-strength information. The following example shows a gate-level design of a tri-state latch. “See Step n” comments in the example correspond to descriptive steps that follow the example.

Example: Instantiating gates

module tri_latch(qout,nqout,clock,data,enable);

 

output qout, nqout;

 

input clock, data, enable;

 

tri qout, nqout;

// See Step 1

not n1(ndata, data);

nand (wa, data, clock), (wb, ndata, clock),

// See Step 2

(q, nq, wa), nand4(nq, q, wb);

// See Step 3

bufif1 q_drive (qout, q, enable),

nqdrive(nqout, nq, enable);

 

endmodule // tri_latch

 

1.Create gate-level designs by instantiating gates. The gate instantiation statement consists of the gate name, optionally followed by an instance name (instance names are useful for debugging), followed by the port list (surrounded by parentheses and separated by commas).

In this example, the not gate has two terminals (output, input). This statement declares a single not instance, with an instance name of n1. Note that the ndata and data ports are not explicitly declared. Verilog HDL allows implicit declarations (wire by default).

2.The nand gate, like the and, or, nor, xor, and xnor gates, has three terminals

(output, input, input). This statement declares four nand instances. Only the fourth has an instance name (nand4).

January 2001

29

Product Version 3.2

Verilog-XL Modeling Style Guide

Modeling Your Hardware (Gate-Level)

3.The bufif1 gate, like the bufif0, notif0, and notif1 gates, has three terminals

(output, input, enable). This statement declares two bufif1 instances called q_drive and nqdrive.

Specifying Drive Strengths

You can specify the output drive strengths for both 0 and 1 values when you instantiate a gate. When you declare drive strengths, you must specify both the 1 and 0 strengths unless the instance is a pullup or pulldown gate. Verilog HDL provides a range of strengths that you can specify. When you do not specify drive strengths, the defaults are strong1 and strong0.

The following example shows how you can instantiate gates with strength specifications. “See Step n” comments in the example correspond to descriptive steps that follow the example.

Example: Specifying drive strengths

module tri_latch(qout, nqout, clock, data, enable);

 

output qout, nqout;

 

input clock, data, enable;

 

tri qout, nqout;

// See Step 1

not n1(ndata, data);

nand (weak1, weak0) (wa, data, clock),

// See Step 2

(wb, ndata, clock),(q, nq, wa), nand4(nq, q, wb);

bufif1 (pull0, strong1) #5 q_drive (qout, q, enable),

// See Step 3

nqdrive(nqout, nq, enable);

endmodule // tri_latch

 

1.To accept Verilog HDL’s default drive strengths of strong0 and strong1, do not specify any drive strengths. You can also explicitly define strengths of (strong1, strong0) to improve readability. The n1 instance has default drive strengths.

2.Specify drive strengths after the gate-type name and before the port list. The strength specification applies to all instances in the statement, so if you want instances of the same gate type with different strengths, use separate statements. This statement declares four nand instances, each with drive strengths of (weak1, weak0).

3.If you specify both strength and delay, the strength must appear before the delay. This statement declares two bufif1 instances (q_drive and nqdrive). Both instances have strengths of (strong1, pull0) and a delay of 5 units.

Specifying Gate Delays

You can assign signal propagation delays when you declare gates. You can define up to three delay types: rising, falling, and transition to high impedance. For each of these delay types,

January 2001

30

Product Version 3.2

Verilog-XL Modeling Style Guide

Modeling Your Hardware (Gate-Level)

you can specify a single delay, or use the min:typ:max format to specify minimum, typical, and maximum delays.

The following example shows how you specify single delays or min:typ:max delays to gate instances. “See Step n” comments in the example correspond to descriptive steps that follow the example.

Example: Specifying gate delays

module tri_latch(qout, nqout, clock, data, enable); output qout, nqout;

input clock, data, enable; tri qout, nqout;

not n1(ndata, data); // See Step 1 nand #(8,9) (wa, data, clock), (wb, ndata, clock); // See Step 2

nand #(8:9:10) (q, nq, wa); // See Step 3

nand #(8:9:10),(10:10:11),(5) nand4(nq, q, wb); bufif1 (strong1,pull0) #(5) // See Step 4 q_drive (qout,q,enable),

nqdrive(nqout, nq, enable); endmodule // tri_latch

1.When you do not specify a delay, the default is zero delay.

2.A delay applies to all instances in a statement, so if you want instances of the same gate type with different delays, use separate statements. You can specify a single delay, two delays (rise time, fall time), or three delays (rise time, fall time, transition to Z ). VerilogXL uses the smallest value for the transition to unknown (X ) and the largest value for the transition from unknown.

This statement declares two nand instances, each with a rise delay of 8, and a fall delay of 9.

3.Specify minimum, typical, and maximum delays for any or all delay values with the

#(min:typ:max) format. The +mindelays, +typdelays, and +maxdelays plus options on the command line select which delay Verilog-XL uses during simulation

(typical delays by default).

4.If you include both strength and delay specifications, the delay must appear after the strength.

This statement declares two bufif1 instances called q_drive and nqdrive. Both instances have strengths of (strong1, pull0) and a delay of 5 units.

Defining Conditional Continuous Assignments

You can create conditional continuous assignments for a net with the conditional operator

(?:). The continuous assignment can be either an explicit assign statement or part of a net

January 2001

31

Product Version 3.2

Verilog-XL Modeling Style Guide

Modeling Your Hardware (Gate-Level)

declaration. Modeling tri-state buses is a common use of a conditional continuous assignment.

Note: You cannot use behavioral conditional statements (if, case) in gate-level designs.

The following example shows how you use the conditional operator in a net declaration to model a tri-state bus. “See Step n” comments in the example correspond to descriptive steps that follow the example. The ?: construct is illustrated in this example.

Example: Defining continuous conditional assignments

module memory_manager(readmem, writemem, clear, address, data);

input readmem, writemem, clear;

 

input [255:0] address;

 

inout [7:0] data;

 

reg [7:0] data_reg;

 

wire readmem, writemem, clear;

 

wire [255:0] address;

 

reg [7:0] mem [255:0];

// See Step 1

wire [7:0] data = readmem ? mem[address] : 8’bz;

event clear_mem;

 

integer i;

 

always @(posedge writemem)

// See Step 2

mem[address] = data;

...

 

1.Use the conditional operator to drive a net with different values based on an expression. The conditional operator is a ternary operator. The first operand is the expression that Verilog-XL evaluates. If the expression is true, Verilog-XL evaluates the second operand. If the expression is false, Verilog-XL evaluates the third operand. If readmem is true (enabled high), then Verilog-XL drives the data onto the data bus. Otherwise, Verilog-

XL tri-states the bus.

2.This statement does not cause bus contention with the continuous assignment to the data bus as long as readmem and writemem are never simultaneously active.

January 2001

32

Product Version 3.2

Verilog-XL Modeling Style Guide

3

Modeling Your Hardware (Behavior-Level)

This chapter describes how to model your hardware at the behavior level.

Defining Procedures That Execute Once ( initial)

When you want to execute a procedure only once—at the beginning of the simulation—use the initial statement. For example, use initial blocks to initialize variables or to define stimulus waveforms. You can have any number of initial blocks.

If you want a procedure to execute continuously throughout a simulation, use an always block.

The following example shows how you use initial blocks to initialize variables or to define stimulus. “See Step n” comments in the example correspond to descriptive steps that follow the example.

Example: Defining procedures that execute once (initial)

module DFF_test; reg clk, clr, d; wire q, qb;

DFF dff1 (d, clk, clr, q, qb);

initial

// See Step 1

begin

// See Step 2

clr=0; d = 0; clk = 0;

$monitor("time = %0t, q = %b", $time, q);

end

 

initial

// See Step 3

begin

 

#80 d = 1;

 

#100 clr = 1; d = 0;

#100 d = 1;

 

#100 $finish;

 

end

 

always

// See Step 4

January 2001

33

Product Version 3.2

Verilog-XL Modeling Style Guide

Modeling Your Hardware (Behavior-Level)

#50 clk = ~clk; endmodule // DFF_test

1.Start an initial block with the initial keyword. Verilog-XL schedules the events in an initial block when the simulation starts. This initial block initializes some variables and sets up a monitor of the system time and output q.

2.If you have more than one statement following an initial or always keyword, you must place your statements in either a begin-end or

fork-join block.

3.A module can have any number of initial blocks. This initial block defines the stimulus to the D flip-flop.

4.For procedures that you want to execute continuously, use an always block. This always block defines the clock waveform. Verilog-XL inverts the clk signal every 50 time units.

Defining Procedures That Execute Continually ( always)

When you want to execute the same procedure throughout a simulation, use the always statement, which is useful for creating waveforms such as clocks, and for executing statements when particular events in your simulation occur. Because Verilog-XL continually executes an always block, specify some timing control (#, @, wait) to keep the procedure from becoming a zero-delay loop.

The following example shows how you use always statements to execute statements based on events in your simulation. “See Step n” comments in the example correspond to descriptive steps that follow the example.

Example: Defining procedures that execute continuously

module

DFF (d, clk, clr, q, qb

);

input clk, clr, d;

 

output

q, qb;

 

reg q,

qb;

 

always

wait(clr==0)

// See Step 1

begin

 

// See Step 2

#4

q=0;

 

#1

qb=1;

 

wait (clr==1);

 

end

 

 

always

@(posedge clk)

// See Step 3

if

(!clr)

 

begin

#8 q = d; #1 qb = ~qb;

January 2001

34

Product Version 3.2

Verilog-XL Modeling Style Guide

Modeling Your Hardware (Behavior-Level)

end

 

endmodule

// DFF

1.Start an always block with the always keyword. Optionally follow the always keyword with a timing-control construct (@ or wait) to specify when Verilog-XL executes the block. Verilog-XL triggers this always block when the clr signal becomes low.

Verilog-XL modifies the outputs of the flip-flop, and then holds up the simulation until clr again goes high— nothing happens to a flip-flop when clr is asserted.

2.If you have more than one statement following an always keyword, you must place your statements in either a begin-end or fork-join block.

3.A module can have any number of always blocks. Verilog-XL executes this block on every positive edge of the clock. If clr is not asserted, Verilog-XL updates the flip-flop outputs q and qb after some delay.

Defining Sequential Blocks ( begin-end)

You can group two or more statements so they act as a single statement by creating blocks. Blocks specify multiple statements as part of an HDL construct that executes a statement, such as initial, always, conditionals, and loops. The begin-end keywords define sequential blocks—statements execute in the order they appear—while fork-join define parallel blocks.

The following example shows how the begin-end keywords define sequential blocks. “See Step n” comments in the example correspond to descriptive steps that follow the example.

Example: Defining sequential blocks (begin-end)

...

 

always @(posedge clk)

// See Step 1

begin

#0 if (!reset)

// See Step 2

begin

inc_pc=0;

 

wait (reset == 1);

// See Step 3

end // ends the if block

else

 

->fetch_instruction;

// See Step 4

#50 d = 2’b00;

#100 d = 2’b01;

 

#200 clr = 1;

 

end // ends the always block ...

 

1.Start a sequential-block definition with the begin keyword. You can give a block a name, which lets you define and reference local variables and reference the block from statements such as the disable statement. See “Disabling Named Blocks and Tasks” on page 46 for an example. This begin starts a sequential block that is part of an always statement.

January 2001

35

Product Version 3.2

Verilog-XL Modeling Style Guide

Modeling Your Hardware (Behavior-Level)

2.You can nest any combination of begin-end and fork-join blocks.

The if-else conditional within the begin-end block requires a begin-end block for the if statements. While you could define a block for the single else statement, a block is not required.

3.End a sequential block with the end keyword.

4.Timing specified within a begin-end block is relative to previous timing specifications within the block. These three assignments execute sequentially. Therefore, the clr=1 statement executes at time 350 (50+100+200).

Defining Parallel Blocks ( fork-join)

You can group two or more statements so they act as a single statement by creating blocks. Blocks specify multiple statements as part of an HDL construct that executes a statement, such as initial, always, conditionals, and loops. The fork-join keywords define parallel blocks — statements execute concurrently — while begin-end define sequential blocks.

The following example shows how the fork-join keywords define parallel blocks and how the begin-end keywords define sequential blocks. “See Step n” comments in the example correspond to descriptive steps that follow the example.

Example: Defining parallel blocks (fork-join)

...

 

always @(posedge clk)

// See Step 1

fork

#0 if (!reset)

// See Step 2

begin

inc_pc=0;

 

wait (reset == 1);

 

end // ends the if block

 

else

 

->fetch_instruction;

// See Step 3

#50 d = 2’b00;

#100 d = 2’b01;

 

#200 clr = 1;

// See Step 4

join

...

 

1.Start a parallel-block definition with the fork keyword. You can give a block a name, which lets you define and reference local variables, and reference the block from statements such as the disable statement. See “Disabling Named Blocks and Tasks” on page 46 for an example.

This fork starts a parallel block that is part of an always statement.

January 2001

36

Product Version 3.2

Соседние файлы в папке dsd-07=Verilog