ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 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