- DataTypes 源自於 http://www.see.ed.ac.uk/~gerard/Teach/Verilog/manual/
- Nets
- Registers
- Vectors
- Numbers
- Arrays
- Tri-state
Nets
Keywords: wire, supply0, supply1default value: z
default size: 1 bit
Nets represent the continuous updating of outputs with respect to their changing inputs. For example in the figure below, c is connected to a by a not gate. if c is declared and initialised as shown, it will continuously be driven by the changing value of a, its new value will not have to be explicitly assigned to it.
If the drivers of a wire have the same value, the wire assumes this value. If the drivers have different values it chooses the strongest, if the strengths are the same the wire assumes the value of unknown, x.
The most frequently used net is the wire, two others which may be useful are supply0, and supply1, these model power supplies in a circuit.
Registers
Keywords: regdefault value: x
default size: 1 bit
The fundamental difference between nets and registers is that registers have to be assigned values explicitly. That value is held until a new assignment is made. This property can, for example, be used to model a E-type flip flop as shown in figure below, with corresponding Verilog code given below.
module E_ff(q, data, enable, reset, clock); output q; input data, enable, reset, clock; reg q; always @(posedge clock) // whenever the clock makes a transition to 1 if (reset == 0) q = 1'b0; else if (enable==1) q = data; // implicitly : else q = q: endmodule
Register q holds the same value until it us changed by an explicit assignment.
As a contrast, if we go into a higher level module, for example the stimulus shown below, the output from the E_ff would have to be assigned as a net so that the E_ff module can drive its value. So now q is a wire.
module stimulus; reg data, enable, clock, reset; wire q; initial begin clock = 1'b0; forever #5 clock = ~clock; end E_ff eff0(q, data, enable, reset, clock); // as with 'c' in the previous section, the wire 'q' will now have its // value driven into it by the E_ff module. initial begin reset = 1'b0; #10 reset = 1'b1; data = 1'b1; #20 enable = 1; #10 data = 1'b0; #10 data = 1'b1; #10 enable = 0; #10 data = 1'b0; #10 data = 1'b1; #10 enable = 1; #10 reset = 1'b0; #30 $finish; end initial $monitor($time, " q = %d", q); endmodule
EXERCISE
Consider the stimulus above and predict the output for q. Then stimulus and check your answer.
Vectors
Both the register and net data types can be any number of bits wide if declared as vectors. Vectors can be accessed either in whole or in part, the left hand number is always the most significant number in the vector. See below for examples of vector declarations.reg [3:0] output; // output is a 4-bit register wire [31:0] data; // data is a 32-bit wire reg [7:0] a; data[3:0] = output; // partial assignment output = 4'b0101; // assignment to the whole register
It is important to be consistant in the ordering of the vector width declaration. Normally the most significant figure is written first.
reg [3:0] a; // it is important to adopt one convention for reg [0:3] b; // the declaration of vector width.
EXERCISE
a) Declare an 8 bit wire with variable name address.
b) Assign 4'b1010 to its 4 most signficant bits.
Numbers
Integers
Keywords: integerdefault value: x
default size: dependant on the host machine, but at least 32 bits
Integers are similar to registers but can store signed (i.e. negative as well as positive numbers) whereas registers can only store positive numbers.
Real numbers
Keywords: realdefault value: x
default size: again host machine dependant, but at least 64 bits
Real numbers can be in decimal or scientific format as shown in the example below. When written with a decimal point, there must be at least one number on either side of the point. A real number is converted to an integer by rounding to the nearest integer.
// 1.3 a real number in decimal format // 1.3e27 a real number in scientific format real pedantic_pi; integer relaxed_pi; initial begin pedantic_pi = 3.141596259; relaxed_pi = pedantic_pi; // relaxed_pi is set to 3 end
A warning about using registers vs. integers for signed values
An arithmetic operation is treated differently depending on the data type of the operand. A register operand is treated as an unsigned value and an integer value is treated as a signed value. Therefore if a negative value, such as -4'd12, is assigned to a register, it will stored as a positive integer which is its 2's complement value. So when used as an operand the 2's complement value will be used causing unintentional behaviour. If stored in an integer, the behaviour would be as expected, using signed arithmetic.
Arrays
Registers, integers and time data types can be declared as arrays, as shown in the example below. Note the size of the array comes after the variable name in the declaration and after the variable name but before the bit reference in an assignment. So :-declaration: <data_type_spec> {size} <variable_name> {array_size}
reference: <variable_name> {array_reference} {bit_reference}
reg data [7:0]; // 8 1-bit data elements integer [3:0] out [31:0]; // 32 4-bit output elements data[5]; // referencing the 5th data element
Memories
Memories are simply an array of registers. The syntax is the same as above, we will discuss modelling RAM and ROM using memories in a later section.reg [15:0] mem16_1024 [1023:0]; // memory mem16_1024 is 1K of 16 bit elements mem16_1024[489]; // referencing element 489 of mem16_1024
It is always good practice to use informative names like mem16_1024 to help keep track of memories.
EXERCISE
Instantiated a 2k memory of 8 bit elements.
Answers
Tri-state
A tri-state driver is one which will output either HIGH, LOW or "nothing".In some architectures, many different modules need to be able to put data onto (to drive) the same bus, at different times. Thus they all connect to the one common bus - but a set of control signals seek to ensure that only one of them is driving a signal at any one time.
In Verilog, this is modelled using different signal "strengths". There is a signal value: z, which is called "high-impedance". This basically means that a node is isolated, that is not driven. It is possible to assign this value to a net.
Normally if two values are simultaneously written to a net, the result is unknown: x; however, if a driven value is also assigned to the same net as a high-impedance value, the driven value will over-ride the z. This is the basis for the following tri-state driver:
module triDriver(bus, drive, value); inout [3:0] bus; input drive; input [3:0] value; assign #2 bus = (drive == 1) ? value : 4'bz; endmodule // triDriver
When the drive signal is high, the bus is driven to the data value, otherwise, this driver outputs only a high-impedance and hence can be over-ridden by any other driven value.
NOTE: the bus is a wire and is designated as an inout variable on the port declarations.
The following example shows the effect of several control combinations on three tri-state buffers:
module myTest; wire [3:0] bus; reg drive0, drive1, drive2; integer i; triDriver mod1 (bus, drive0, i[3:0]); triDriver mod2 (bus, drive1, 4'hf); triDriver mod3 (bus, drive2, 4'h0); initial begin for (i = 0; i < 12; i = i + 1) begin #5 {drive2, drive1, drive0} = i; #5 $display ($time," %b %b %d", i[2:0], bus, bus); end $finish; end // initial begin endmodule // myTest
giving output:
10 000 zzzz z 20 001 0001 1 30 010 1111 15 40 011 xx11 X 50 100 0000 0 60 101 0x0x X 70 110 xxxx x 80 111 xxxx x 90 000 zzzz z 100 001 1001 9 110 010 1111 15 120 011 1x11 X
沒有留言:
張貼留言