Verilog Basic Syntax and Notes

Time:2024-5-17

basics

0.1 Modules

A module in Verilog can be viewed as a black box with input and output ports, which has input and output interfaces (signals) to realize a function by putting inputs in the box to perform certain operations. (Similar to a function in C).

Verilog Basic Syntax and Notes

Fig. 1 Schematic diagram of the module

0.1.1 Module description

The top_module structure shown in Figure 1 can be described in Verilog language as:

module  top_module(
    input a,
    input b,
    output out
);

   ....... 

endmodule
  • Modules start with module and end with endmodule.
  • top_module is the module name
  • input : is the input port
  • output: is the output port
  • All code must be in a module

Similarly, the structure of the sub-module (mod_a) shown in Figure 1 can be described in Verilog language as:

module  top_module(
    input in1,
    input in2,
    output out
);

   ....... 

endmodule

caveatEach module should be in a separate block in a .v file, with the module name being the file name(Regulate the code!)

0.1.2 Module Input and Output Signals

  • Output: output
  • Input: input

The input and output ports of the module are visible to the module’s signals, and if the signal type is not written theDefaults to wire type signal

// The following two statements are essentially the same thing
input a;

input wire a;

In addition to the WIRE type signal, there is also the REG type signal, for details see1.4Sections!

0.1.3 Module instantiation

As shown in Figure 1, the two input ports of top_module are connected to the input ports of the sub-module (mod_a), so how to use the functions of mod_a module in top_module module? This requires module instantiation, you can think of top_module as a main function in C and the sub-module mod_a as an ordinary function, so that you can call other functions in the main function to complete the corresponding functions!

Instantiate mod_a in top_module as:

Module Instantiation Syntax: module name instance name (defines the signals for connecting to the port).

module  top_module(
    input a,
    input b,
    output out
);

	mod_a instance2 (.in1(a), .in2(b), .out(out));

endmodule
  • Instantiate the ports in the order in which mod_a defines them: mod_a instance1 (a, b, out);
  • Instantiate by mod_a port name: mod_a instance2 (.in1(a), .in2(b), .out(out)); (recommended)

0.2 Logical block (always, generate)

0.2.1 always logic block

Always blocks can be constructed as combinatorial logic blocks and timing logic blocks, which are required for complex logic operations such as if, case, for, etc.

(1) Combination Logic Block

module top_module();

    always @(*) begin
        ....
    end

endmodule
  • In the always logic blockTriggered immediately upon any signal changeThe statement between begin – end is executed.
  • begin-end is usedForming multiple statements into a single code blockIf there is only one statement, it can be omitted.

(1) Timing logic circuits

module top_module();

    always @(posedge clk) begin
        ....
    end

endmodule
  • clk Rising edge trigger of the signal
  • posedge: rising edge
  • negedge: falling edge

0.2.2 generate logical block

generate is mainly used in conjunction with for loops, and its main uses are:

  • rightvectorsRepeat operation for multiple bits in
  • Multiple repeated instantiations of the same module(Primary use)

(1) Operation Vector

module top_module(input [7:0] in,  output [7:0] out);
    genvar i; // genvar i; can also be defined within generate
    generate
        for(i=0; i<8; i++) begin: bit
             assign out[i]=^in[8-1:i];
        end
    endgenerate
endmodule

(2) Repeated Instantiation of Modules Multiple Times

module  top_module(
    input a,
    input b,
    output out
);
    genvar i;
    generate
        for(i=0; i<8; i++) begin: gen_mod_a // gen_mod_a is the name of the structure for each begin_end
            mod_a instance2 (.in1(a), .in2(b), .out(out));
        end
    endgenerate
endmodule
  • Note: When the module is instantiated multiple timesMust write the name of each begin_end structure(gen_mod_a)
  • The emulator will identify the generated structure by gen_mod_a: gen_mod_a[0],gen_mod_a[1]….

0.2.3 initial block

The initial block can be interpreted as ainitialization blockThe statement at the start of the initialExecution begins at time 0, and if a delay is encountered, the next statement is executed after the delay.

The initial block isirresolvableThereforeIt cannot be translated into a hardware schematic with digital elements. Therefore the initial block is not very useful except for use in simulation

E.g.:Initialize various parameters in the simulation file:

initial                                                
begin                                                  
    sys_clk    = 1'b1;                
    sys_rst_n  = 1'b0; 
	#50
	sys_rst_n  = 1'b1;                
end  

Caution:

  • The initial block is not synthesizable in the circuit, so it does not normally appear in RTL code.
  •  initial Generally only used in simulation files

If you need to initialize parameters in RTL code, you need to use the always block, using the initial block will result in an error!

As shown below.Initialize the memory in the RTL code in the following way

reg [255:0]char_data[4:0];

always@(posedge clk)
    begin
        char_data[0]     <=  256'h0000000000000000000000000000000000000000000000000000000000000000;
        char_data[1]     <=  256'h0000000000000000000000000000000000000000000000000000000000000000;
        char_data[2]     <=  256'h0000000000000000000000200000000000000000002000000008000010000000;
        char_data[3]     <=  256'h000000000000000000000038000000000000020000380000000600001C000000;
        char_data[4]     <=  256'h02000000000100000000003E0000000000000700003E0000000780001F000000;
    end

0.3 Mode of assignment

There are three types of assignment in Verilog: sequential, blocking, and non-blocking.

0.3.1 Successive assignments (assign)

assign x = y;
  • This statement represents the connection of the two signals x and y.Real Physical Connections
  • Cannot be used in an always block

0.3.2 Blocking assignment (=)

// Combination blocks
always @(*)  begin
	out1 = a ;
    a = b ;
    out2 = a ;
end
  • Blocking assignment in the combination always block
  • Execution order: follow the begin_end statement block in thesequential execution, the above output is: out1 = a , out2 = b

0.3.3 Non-blocking assignments (<=)

// Timing blocks
always @(posedge clk)  begin
	out1 <= a ;
    a <= b ;
    out2 <= a ;
end
  • Non-blocking assignments in the timingalways block with the
  • Order of execution: in begin_endAll statements are executed in parallel, the output of the above is: out1 = a , out2 = a


Chapter 1: Basic Grammar

1.1 Identifiers

(1) Purpose: Identifiers are used to define constants, variables, signals, ports, parameter names, module names, and so on.

(2) Composition: letters, numbers, $, underline any combination of

(3) Caveats:

  • Case sensitive (Verilog and verilog are different)
  • The first character can only be a letter or an underscore(123demo is an illegal identifier)

1.2 Logical Values and Logical Operations

1.2.1 Logical values

There are 4 logic values in Verilog: 0, 1, x, z

  • 0: low level
  • 1: High level
  • x: indicates unknown status
  • z: indicates a high resistance state

Note: Here z and x arenot distinguishing capitals from lower case letters(X and Z are also possible)

1.2.2 Logical operations

(1) Logical operators: && (with), == (equal), || (or), ! = (not equal)

  • e.g. m&&n : determine whether m and n are all true (Non-zero is true), true outputs 1’b1, otherwise outputs 1’b0 (4’b1010&4’b0101 =1’b1)
  • final outputThe result is only 1 bit

(2) Bitwise operators: &, |, ~, ^, ~&, ~^, ~|

  • e.g. m&n : is to do a bitwise sum of each bit of m and each bit of n (4’b1010&4’b0101 =4’b0000)
  • The output is the same number of bits as m/n

(3) Normalization operators: &, |, ~, ^, &, ~^, ~|

  • When there is only one parameter involved in the operation (& is a unary operator), it means that the statute and, i.e., the vector is internally operated on.
&a [3:0] // AND:a[3]&a[2]&a[1]&a [0] is equivalent to (a[3:0]== 4'hf)
|b [3:0] // OR: b[3]|b[2]|b[1]|b [0] is equivalent to (b[3:0]! = 4'h0)
^c [2:0] // XOR:c[2]^c[1]^c[0]
  • That is (&4 ‘b0101 = 0&1&0&1 =1’b0 )
  • final outputThe result is only 1 bit

1.3 Representation of constants

Similar to C, there are three main types of constants: integer, real and string.

1.3.1 Representing Integer Constants as Decimal Integers

(1) Positive numbers: write 10 directly to indicateA decimal integer with a bit width of 32 bits.(system default)

(2) Negative numbers: -10 needs to be expressed in binary complement with one extra sign bit (1 1010)

(3) In scientific notation: 12.345e3 for 12345

1.3.2 Representation of integer constants by the base method

[Bit width after conversion to binary]'[Number system notation][Value corresponding to number system]

(1) Binary (b): 8’b1000_1100

(2) Hex (h): 8’h8c

(3) Octal (o): 8’o214

(4) Decimal (d): 8’140

Caveats:

  • When representing binary, it is best to write an underscore every 4 bits to enhance readability: e.g. 8’b1000_1100 is the same as 8’b10001100.
  • In the base representationWhen x is encountered: 4 x in hexadecimal, 3 x in octal
  • When the bit width is greater than the number of binary digits, the left side is automatically complemented with 0, and 2 is truncated from the left side when it is less than the number of binary digits.

1.3.3 Strings (in double quotes)

(1)each characterRepresented by 1 8-bit ASCII value, i.e., requires 1 byte of storage space

(2) As:“Hello world”  The string consists of 11 ASCII symbols and requires 11 byte of storage space

1.3 Mode of annotation

Verilog in the comments are mainly line comments (//) and block comments (/* …. */) two kinds, the representation is consistent with the C language!

// Line comments

/*
        block note

*/

1.4 Variables (wire, reg)

There are two main types of variables in Verilog: wire and reg

1.4.1 wire

(1) Wire: represents the physical connection between circuits, the variables defined by wire can also be viewed assignal port

(2) When two WIRE signals are assigned consecutively, they are mapped to real physical connections in the logic block, theAt this point the changes in these two signal ports are synchronized

wire a;

wire b;

assign b = a; // indicates that an actual physical connection between a and b is generated

1.4.2 reg

(1) Register type (reg): represents aAbstract data storage unit

(2) reg has a function to maintain the state at a certain point in time.

1.4.3 Usage and Precautions

(1) inalways、initialThe variable that is assigned a value in the statement (The variable to the left of the assignment number) areregvariant

(2) InassignThe variable that is assigned a value in the statement for thewirevariant

1.5 Vectors and Parameters (Constants)

1.5.1 parameter Parameter (constant)

(1) A parameter is a constant that usually appears in theInside the moduleThe following are some examples of the types of data that can be used to define status, data bit widths, etc.

parameter STATE = 1'b0;

(2) Only works on the file where it is declared and can be changed flexibly

(3) Local parameter localparam, used only in this module.

localparam  STATE= 1'b1’;

(4) The name of the parameter is usuallyuppercase lettersto distinguish other variables

1.5.2 vector

vector (vector) that isA collection of signalsIf the bit width is more than 1 bit, it can be regarded as a wire signal with a bit width of more than 1 bit.

(1) Define modalities:

The format is input/output wire/reg [upper:lower] vector_name

// Input-output type
input [7:0] a,b,
output reg [7:0] out

// Module intermediate vectors
wire [7:0] c, e;
reg [7:0] d;
  • [upper:lower] defines the bit width, e.g. [7:0] means the bit width is 8 bit, i.e., upper=7, lower=0.
  • vector_name can be used onceWrite multiple vectors

1.5.3 Vector slice selection

  • a[3:0] Orientation of bits 0 to 4 of quantity a
  • b[n] Orientation of the nth data position of the quantity b
  • c[-1:-2] Orienting the most significant part of the quantity cLow 2nddigital
  • c[0:3] Orientation of the most significant part of the quantity cHigh 4digital

Multiple selector application: implement a 256 select 1 selector, sel signal is used as the selection signal, in[3:0] is selected when sel = 0, in[7:4] is selected when sel = 1, and so on.

module top_module (
	input [1023:0] in,
	input [7:0] sel,
	output [3:0] out
);
	assign out = {in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0]};

	// assign out = in[sel*4 +: 4];		
	// assign out = in[sel*4+3 -: 4];	
endmodule
  • The chip-select signal sel input is an n-bit binary number whenParticipate in operations, act as an indexwill be automatically converted to decimal numbers when
  • The signal fragment chosen for this question is: in[sel*4+3: sel*4] , but this does not conform to Verilog’s piecewise syntax rules and should be written as:
    in[sel*4 +: 4]  Indicates that the index starts at sel*4High 4bit signal
    in[sel*4+3 -: 4] means that the index starts from sel*4+3Low 4bit signal
  • either one or the otherDirectly select everyone who needs it, which is then spliced into a new vector with { }:
    {in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0]}

Reference Article:HDLBits: Online learning Verilog (XIII · Problem 60-64) – zhihu.com

1.6 Ternary expressions

(1) As with C, Verilog also hasternary expression

condition ? if_true : if_false

When the condition is true, the expression evaluates to if_true , otherwise the expression evaluates to if_false.

(2) Applications

(sel ? b : a) // A binary MUX that selects a or b by the value of sel.

always @(posedge clk) // a T-trigger
  q <= toggle ? ~q : q;

assign out = ena ? q : 1'bz;  // Three-state buffer

(3) Reference articles:HDLBits: Online learning Verilog (VIII · Problem 35-39) – zhihu.com

1.7 Branching Statements (if-else, case)

1.7.1 if-else statements

(1) Most commonly used form: (Advantage:All possibilities for the output are written, there are no unknown level outputs!)

if(<conditional expression 1>)
    Statement or block of statements 1.
else if(<conditional expression 2>)
    statement or block of statements 2.
    ………
else
    statement or block of statements n.

(2) if-else nesting is not recommended, there will be prioritization issues which will lead to confusion in the logic.

(3)  All if-else statements should be written in the form (1)

(4) Compare, in order, according to the conditional expression.Priority exists

1.7.2 The case statement

(1) Writing form:

case(<control expression>)
    <branching statement 1> : block 1.
    <branching statement 2> : block 2.
    <branching statement 3> : statement block 3.
    ………
    <branching statement n> : statement block n.

    default : statement block n+1;
endcase

Compare <control expression> with <branch statement n> and execute the corresponding statement if the values are equal, otherwise execute the statement after default!

(2) Jumping out of the case statement structure immediately after executing a branching statement, terminates case statement execution.

(3) <branching statement n>The value of mustnot the same as each other

(4) End with encasecase statement block

(5) Between branching statementsNo prioritization

(6) Specific application: use case statement to build a multiplexer, (take the example of 9 choose 1 multiplexer)

module top_module( 
    input [15:0] a, b, c, d, e, f, g, h, i,
    input [3:0] sel,
    output [15:0] out );
    always @(*) begin
        case(sel)
            4'h0:begin out = a; end
            4'h1:begin out = b; end
            4'h2:begin out = c; end
            4'h3:begin out = d; end
            4'h4:begin out = e; end
            4'h5:begin out = f; end
            4'h6:begin out = g; end
            4'h7:begin out = h; end
            4'h8:begin out = i; end
            default: out = 16'hffff;
        endcase
    end
endmodule

1.8 for Loop Statements

(1) Writing form:

integer i;
always @(*)  begin 
    for(i=0; i<n; i++)  begin: for_name
        <loop statement>
    end
end
  • Execute <loop statement>n times
  • for_name is the name of each loop

1.9 Relational operators (>, <, >=, <=)

  • Returns 1 if the result is true
  • Returns 0 if the result is false
  • If an operationNumerically indeterminate (x), then the return value is x

2.0 Splice Operators ({ , })

2.0.1 Splice

Use a pair of parentheses with commas to form “{ , }“Splicing operator, comma-separated dataSequential splicing into new data

wire [1:0] a;
wire [3:0] b;
wire [5:0] c;
wire [11:0] d = {a, b, c} 

2.0.2 Shifting by splicing

Splice on the left to achieve a right shift and splice on the right to achieve a left shift!

always @(posedge clk) begin
    if(rst_n == 1'b0)
        out <= 4'b0;
    else
        out <= {in, out[3:1]};    // Move right
end

2.0.2 Repeat Multiple Operations in Connectors

Grammar:{repeat count {vector}}

{3{a}} = {a, a, a}
{3'd5, {2{3'd6}}}   // 9'b101_110_110.

2.1 Shift Operators

The shift operator is used to shift the left operand left or right by the specified number of bits!Free bits are filled with zeros after shifting

  • Left shift operator: <<

e.g. 4’b1101 << 3 results in: 4’b1000

  • Right-shift algorithmic symbols: >>

e.g. 4’b1101 >> 3 Result: 4’b0001

  • Other uses of shift operators:Shifting one place to the left can be thought of as multiplying by 2, and shifting one place to the right can be thought of as dividing by 2
  • Shift operators instead of multiplication and division can save resources!

3 Binary Full Adder

Verilog Basic Syntax and Notes

  • a, b are input 1bit data
  • cin is the last adder input.
  • cout is the rounded output of this adder.
  • sum = a+b

Verilog Basic Syntax and Notes

Code Implementation:

module add1 (
	input a,
	input b,
	input cin,	
	output sum,
	output cout
);
	assign sum = a^b^cin;
	assign cout = (a&b) | (a&cin) | (b&cin);
endmodule

4 Hexadecimal Full Adder

Verilog Basic Syntax and Notes

The hexadecimal full adder is shown above, and it can be combined from the 16 binary full adders in the previous section.

The code to implement the hexadecimal full adder in Verilog is:

module add16 (	
	input [15:0] a,
	input [15:0] b,
	input cin,
	
	output [15:0] sum,
	output cout
);
	wire [16:0] Add_cin;
	assign Add_cin[0] = cin; // The first binary adder feed input in the above figure is 0 assign Add_cin[0] = 1b'0;

// Multiple instantiation of modules with generate
// generate Applications: repeated operations on multiple bits of a vector, repeated instantiation of modules
	genvar i;
	generate
		for(i=0; i<16; i++) begin: gen_add16 // gen_add16 is the structure for each begin_end, the emulator will identify the generated structure by him, gen_add16[0],gen_add16[1]....
			add1 Add16(.a(a[i]), .b(b[i]), .cin(Add_cin[i]), .sum(sum[i]), .cout(Add_cin[i+1]));
		end
	
	endgenerate
	
	assign cout = Add_cin[16];

endmodule

5 Parameter Passing in Modules

5.1 Defining modules that can be passed parameters

module counter
// Parameter passing
#(
    parameter COUNT_MAX = 25'd24_999_999,
    parameter STATE = 1'b0 // multiple parameters separated by commas
)
(
    input  wire  sys_clk,
    output reg led_out
);
// Code body
endmodule

5.2 Instantiation of modules with parameters

// Parameter passing
#(
   .COUNT_NUM( 25'd24_999_999), // incoming parameters
   .STATE(1'b0)
)
counter1_init // Name location of the instantiation module
(
    .sys_clk   (sys_clk),
    .led_out(led_out)
);

References:

[1] Wildfire’s Practical Guide to FPGA Verilog Development:[Wildfire] FPGA Verilog Development Practical Guide – Based on the Altera EP4CE10 Journey Pro Development Board – [Wildfire] FPGA Verilog Development Practical Guide -… Based on the Altera EP4CE10 Journey Pro Development Board Documentation (embedfire.com)Verilog Basic Syntax and Noteshttps://doc.embedfire.com/fpga/altera/ep4ce10_pro/zh/latest/index.html

[2] HDLBits Chinese guide:HDLBits Chinese Guide – zhihu.com

Recommended Today

Unable to save ip settings, prompted to check one or more settings and try again.

Some users upgraded their computers to Win11 system, they want to set ip, but they found that they can’t save ip settings please check one or more settings and retry, how do we solve it? Pure Home – win7 pure version system_win7 ghost pure version cure 1, “win + R” shortcut key to open the […]