ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 14.06.2025
Просмотров: 441
Скачиваний: 0
Introduction to Verilog
11. Functions
Functions are declared within a module, and can be called from continuous assignments, always blocks or other functions. In a continuous assignment, they are evaluated when any of its declared inputs change. In a procedure, they are evaluated when invoked.
Functions describe combinational logic, and by do not generate latches. Thus an if without an else will simulate as though it had a latch but synthesize without one. This is a particularly bad case of synthesis not following the simulation. It is a good idea to code functions so they would not generate latches if the code were used in a procedure. Functions are a good way to reuse procedural code, since modules cannot be invoked from a procedure.
11.1. Function Declaration
A function declaration specifies the name of the function, the width of the function return value, the function input arguments, the variables (reg) used within the function, and the function local parameters and integers.
Syntax, Function Declaration
function [msb:lsb] function_name; input [msb:lsb] input_arguments; reg [msb:lsb] reg_variable_list; parameter [msb:lsb] parameter_list; integer [msb:lsb] integer_list;
... statements ...
endfunction
Example 11 .1
function [7:0] my_func; // function return 8-bit value input [7:0] i;
reg [4:0] temp; integer n;
temp= i[7:4] | ( i[3:0]); my_func = {temp, i[[1:0]};
endfunction
11.2. Function Return Value
When you declare a function, a variable is also implicitly declared with the same name as the function name, and with the width specified for the function name (The default width is 1-bit). This variable is “my_func” in Example 11 .1 on page 19. At least one statement in the function must assign the function return value to this variable.
11.3. Function Call
As mentioned in Sect. 6.4. , a function call is an operand in an expression. A function call must specify in its terminal list all the input parameters.
11.4. Function Rules
The following are some of the general rules for functions:
-Functions must contain at least one input argument.
-Functions cannot contain an inout or output declaration.
-Functions cannot contain time controlled statements (#, @, wait).
-Functions cannot enable tasks.
-Functions must contain a statement that assigns the return value to the implicit function name register.
Friday, January 05, 2001 9:34 pm |
19 |
Peter M. Nyasulu |
Introduction to Verilog
11.5. Function Example
A Function has only one output. If more than one return value is required, the outputs should be concatenated into one vector before assigning it to the function name. The calling module program can then extract (unbundle) the individual outputs from the concatenated form. Example 11.2 shows how this is done, and also illustrates the general use and syntax of functions in Verilog modeling.
Syntax
function_name = expression
Example 11 .2
module simple_processor (instruction, outp); input [31:0] instruction;
output [7:0] outp;
reg [7:0] outp;; // so it can be assigned in always block reg func;
reg [7:0] opr1, opr2;
function [16:0] decode_add (instr) // returns 1 1-bit plus 2 8-bits input [31:0] instr;
reg add_func;
reg [7:0] opcode, opr1, opr2; begin
opcode = instr[31:24]; opr1 = instr[7:0]; case (opcode)
8’b10001000: begin |
// add two operands |
add_func = 1; |
|
opr2 = instr[15:8]; |
|
end |
|
8’b10001001: begin |
// subtract two operands |
add_func = 0; |
|
opr2 = instr[15:8]; |
|
end |
|
8’b10001010: begin |
// increment operand |
add_func = 1; |
|
opr2 = 8’b00000001; |
|
end |
|
default: begin; |
// decrement operand |
add_func = 0; |
|
opr2 = 8’b00000001; |
|
end |
|
endcase |
decode_add = {add_func, opr2, opr1}; // concatenated into 17-bits end
endfunction
// ----------------------------------------- ---------------------------------
always @(instruction)begin
{func, op2, op1} = decode_add (instruction); // outputs unbundled if (func == 1)
outp = op1 + op2; else
outp = op1 - op2;
end endmodule
Friday, January 05, 2001 9:34 pm |
20 |
Peter M. Nyasulu |
Introduction to Verilog
12. Tasks Not Synthesizable
A task is similar to a function, but unlike a function it has both input and output ports. Therefore tasks do not return values. Tasks are similar to procedures in most programming languages. The syntax and statements allowed in tasks are those specified for functions (Sections 11).
Syntax
task task_name;
input [msb:lsb] input_port_list; output [msb:lsb] output_port_list; reg [msb:lsb] reg_variable_list; parameter [msb:lsb] parameter_list; integer [msb:lsb] integer_list;
... statements ...
endtask
Example 12 .1
module alu (func, a, b, c);
input [1:0] func; |
|
input [3:0] a, b; |
|
output [3:0] c; |
|
reg [3:0] c; |
// so it can be assigned in always block |
task my_and; input[3:0] a, b; output [3:0] andout; integer i;
begin
for (i = 3; i >= 0; i = i - 1) andout[i] = a[i] & b[i];
end endtask
always @(func or a or b) begin case (func)
2’b00: my_and (a, b, c); 2’b01: c = a | b;
2’b10: c = a - b; default: c = a + b;
endcase end endmodule
Friday, January 05, 2001 9:34 pm |
21 |
Peter M. Nyasulu |
Introduction to Verilog
13. Component Inference
13.1. Latches
A latch is inferred (put into the synthesized circuit) if a variable is not assigned to in the else branch of an if ... else if
... else statement. A latch is also inferred in a case statement if a variable is assigned to in only some of the possible case choice branches. Assigning a variable in the default branch avoids the latch. In general, a latch is inferred in if ...
else if ... else and case statements if a variable, or one of its bits, is only assigned to in only some of the possible branches.
To improve code readability, use the if statement to synthesize a latch because it is difficult to explicitly specify the latch enable signal when using the case statement.
Syntax |
Example 13 .1 |
||||||||||||||||
See Sections 8.9 and 8.10 for |
always @(c, i); |
i |
|||||||||||||||
D |
|||||||||||||||||
if ... else if ... else and case statements |
begin; |
Q |
o |
||||||||||||||
if (c == 1) |
c |
EN |
|||||||||||||||
o = i; |
|||||||||||||||||
end |
|||||||||||||||||
13.1. Edge-Triggered Registers, Flip-flops, Counters
A register (flip-flop) is inferred by using posedge or negedge clause for the clock in the event list of an always block. To add an asynchronous reset, include a second posedge/negedge for the reset and use the if (reset) ... else statement. Note that when you use the negedge for the reset (active low reset), the if condition is (!reset).
Syntax
always @(posedge clk or posedge reset_1 or negedge reset_2)
begin
if (reset_1) begin
... reset assignments end
else if (!reset_2) begin
... reset assignments end
else begin
...register assignments end
end
Example 0 .1
CLR |
||||||||||||||||||||||||||||||||||||||
always @(posedge clk); |
b |
|||||||||||||||||||||||||||||||||||||
D |
||||||||||||||||||||||||||||||||||||||
begin; |
c |
|||||||||||||||||||||||||||||||||||||
a <= b & c; |
Q |
a |
||||||||||||||||||||||||||||||||||||
end |
clk |
CLK |
||||||||||||||||||||||||||||||||||||
always @(posedge clk or |
||||||||||||||||||||||||||||||||||||||
rst |
||||||||||||||||||||||||||||||||||||||
negedge rst); |
||||||||||||||||||||||||||||||||||||||
begin; |
CLR |
|||||||||||||||||||||||||||||||||||||
b |
D |
|||||||||||||||||||||||||||||||||||||
if (! rst) |
a< = 0; |
|||||||||||||||||||||||||||||||||||||
else |
a <= b; |
Q |
a |
|||||||||||||||||||||||||||||||||||
end |
clk |
|||||||||||||||||||||||||||||||||||||
CLK |
||||||||||||||||||||||||||||||||||||||
Example 0 .2 An Enabled Counter reg [7:0] count;
wire enable;
always @(posedge clk or posedge rst) // Do not include enable. begin;
if (rst) count<=0;
else if |
(enable) count <= count+1; |
end; |
// 8 flip-flops will be generated. |
Friday, January 05, 2001 9:34 pm |
22 |
Peter M. Nyasulu |
Introduction to Verilog
13.2. Multiplexers
A multiplexer is inferred by assigning a variable to different variables/values in each branch of an if or case statement. You can avoid specifying each and every possible branch by using the else and default branches. Note that a latch will be inferred if a variable is not assigned to for all the possible branch conditions.
To improve readability of your code, use the case statement to model large multiplexers.
Syntax
See Sections 8.9 and 8.10 for
if ... else if ... else and case statements
Example 13 .2
if (sel == 1) y = a;
else
y = b;
case (sel) 2’b00: y = a; 2’b01: y = b; 2’b10: y = c;
default: y = d; endcase
sel
a
y
b
sel[1:0]
a b
c |
y |
||||
d |
|||||
13.3. Adders/Subtracters
The +/- operators infer an adder/subtracter whose width depend on the width of the larger operand.
Syntax |
Example 13 .3 |
sel |
|||||||||||||
See Section 7 for operators |
if (sel == 1) |
a |
|||||||||||||
c |
|||||||||||||||
y = a + b; |
+ |
||||||||||||||
sel |
y |
||||||||||||||
else |
|||||||||||||||
b |
|||||||||||||||
y = c + d; |
d |
||||||||||||||
13.4. Tri-State Buffers
A tristate buffer is inferred if a variable is conditionally assigned a value of z using an if, case or conditional operator.
Syntax |
Example 13.5 |
|||||||||||||||
See Sections 8.9 and 8.10 for |
if (en == 1) |
en |
||||||||||||||
if ... else if ... else and case statements |
y = a; |
a |
y |
|||||||||||||
else |
||||||||||||||||
y = 1’bz; |
||||||||||||||||
13.5. Other Component Inferences
Most logic gates are inferred by the use of their corresponding operators. Alternatively a gate or component may be explicitly instantiated by using the primitive gates (and, or, nor, inv ...) provided in the Verilog language.
Friday, January 05, 2001 9:34 pm |
23 |
Peter M. Nyasulu |
Introduction to Verilog
14. Finite State Machines. For synthesis
When modeling finite state machines, it is recommended to separate the sequential current-state logic from the combinational next-state and output logic.
State Diagram
for lack of space the outputs are not shown on the state diagram, but are:
in state0: Zot = 000, in state1: Zot = 101, in state2: Zot = 111, in state3: Zot = 001.
start=0
reset=1 |
|||
state0 |
|||
wait3=0 |
start=1 |
||
state3 |
skip3=1 |
state1 |
|
wait3=1 |
|||
skip3=0 |
|||
state2 |
|||
Using Macros for state definition
As an alternative for- parameter state0=0, state1=1,
state2=2, state3=3;
one can use macros. For example after the definition below 2'd0 will be textually substituted whenever `state0 is used. `define state0 2'd0
`define state1 2'd1 `define state2 2'd `define state3 2'd3;
When using macro definitions one must put a back quote in front. For example: case (state)
`state0: Zot = 3’b000; `state1: Zot = 3’b101; `state2: Zot = 3’b111; `state3: Zot = 3’b001;
Example 14 .1
module my_fsm (clk, rst, start, skip3, wait3, Zot); input clk, rst, start, skip3, wait3;
output [2:0] Zot; // Zot is declared reg so that it can reg [2:0] Zot; // be assigned in an always block. parameter state0=0, state1=1, state2=2, state3=3; reg [1:0] state, nxt_st;
always @ (state or start or skip3 or wait3)
begin : next_state_logic //Name of always procedure. case (state)
state0: begin
if (start) nxt_st = state1; else nxt_st = state0; end
state1: begin
nxt_st = state2; end
state2: begin
if (skip3) nxt_st = state0; else nxt_st = state3;
end
state3: begin
if (wait3) nxt_st = state3; else nxt_st = state0;
end default: nxt_st = state0;
endcase |
// default is optional since all 4 cases are |
end |
// covered specifically. Good practice says uses it. |
always @(posedge clk or posedge rst) begin : register_generation
if (rst) state = state0; else state = nxt_st;
end
always @(state) begin : output_logic case (state)
state0: Zot = 3’b000; state1: Zot = 3’b101; state2: Zot = 3’b111; state3: Zot = 3’b001;
default: Zot = 3’b000;// default avoids latches endcase
end endmodule
Friday, January 05, 2001 9:34 pm |
24 |
Peter M. Nyasulu |