IEEE 2001矢量、generate

IEEE 2001 重点

矢量位选择和部分选择寻址

Vector bit-select and part-select addressing

操作符 +:与 -:

//Examples:
reg [31:0] big_vect; 
reg [0:31] little_vect; 
reg [63:0] dword; integer sel;
//The first four if statements show the identity between the two part select constructs. The last one shows an indexable nature. 
initial begin 
    if (   big_vect[0  +:8] ==    big_vect[7  : 0])  begin end 
    if (little_vect[0  +:8] == little_vect[0  : 7])  begin end  
    if (   big_vect[15 -:8] ==    big_vect[15 : 8])  begin end  
    if (little_vect[15 -:8] == little_vect[8  :15])  begin end  
    if (sel >0 && sel < 8)  
        dword[8*sel +:8] = big_vect[7:0]; // Replace the byte selected.

+: 为升序 -: 为降序

big_vect称为大端,little_vect称为小端; 经过 +: 和 -: 转换后,仍为大端和小端,形式不变

big_vect    [0  +:   8]  从0 开始,升序,位宽为8     ======》》》》》big_vect   [7 :0]
little_vect  [0  +:   8]  从0 开始,升序,位宽为8     ======》》》》》little_vect  [0 :7]
big_vect   [15 -:   8]  从15开始,降序,位宽为8    ======》》》》》big_vect    [15 :8] 
little_vect [15 -:   8]  从15开始,降序,位宽为8    ======》》》》》little_vect   [8:15]

在这里插入图片描述
在这里插入图片描述

Array and memory addressing数组与内存寻址

Array and memory addressing

//256x256字节的8bit存储器;256x256x8 bit线网
reg [7:0] twod_array[0:255][0:255];
wire threed_array[0:255][0:255][0:7]; 

The syntax for access to the array shall consist of the name of the memory or array and an expression for each addressed dimension:
访问数组的语法应包括内存或数组的名称以及每个寻址维度的表达式:
twod_array[addr_expr][addr_expr] threed_array[addr_expr][addr_expr][addr_expr]
As before, the addr_expr can be any expression. The array twod_array accesses a whole 8-bit vector, while the array threed_array accesses a single bit of the three dimensional array.
如前所述,addr_expr可以是任何表达式。数组twod_array访问整个8位向量,而数组threed_array访问三维数组的单个位
To express bit selects or part selects of array elements, the desired word shall first be selected by supplying an address for each dimension. Once selected, bit and part selects shall be addressed in the same manner as net and reg bit and part selects (see 4.2.1).
为了表示数组元素的位选择或部分选择,应首先通过为每个维度提供地址来选择所需的字。
一旦选定,位、数据段的寻址方式与线网、寄存器寻址方式相同

//Examples:
twod_array[14][1][3:0]      // access lower 4 bits of word 访问字的低四位
twod_array[1][3][6]         // access bit 6 of word 访问字的第六位
twod_array[1][3][sel]       // use variable bit select 访问字的第sel位
threed_array[14][1][3:0]    // Illegal 非法访问

String operands字符串的操作

String operands shall be treated as constant numbers consisting of a sequence of 8-bit ASCII codes, one per character.

字符串操作数应视为常数,由8位ASCII码序列组成,每个字符一个。

Any VerilogHDL operator can manipulate string operands. The operator shall behave as though the entire string were a single numeric value.

任何Verilog HDL运算符都可以操作字符串。运算符对待整个字符串和对待单个数值是一样的。

扫描二维码关注公众号,回复: 12679060 查看本文章

When a variable is larger than required to hold the value being assigned, the contents after the assignment shall be padded on the left with zeros. This is consistent with the padding that occurs during assignment of nonstring values.

当一个变量大于保存赋值所需的值时,赋值后的内容应在左边用零填充。这与非字符串值赋值过程中出现的填充一致。

module string_test; 
    reg [8*14:1] stringvar;
	initial begin stringvar = "Hello world";
        $display("%s is stored as %h", stringvar, stringvar); 
        stringvar = {stringvar,"!!!"}; 
        $display("%s is stored as %h", stringvar, stringvar); 
end endmodule

Hello world is stored as 00000048656c6c6f20776f726c64

Hello world!!! is stored as 48656c6c6f20776f726c64212121

reg [8*10:1] s1, s2; 
initial begin 
    s1 = "Hello"; 
    s2 = " world!"; 
    if ({s1,s2} == "Hello world!") 
        $display("strings are equal"); 
end

s1 = 000000000048656c6c6f

s2 = 00000020776f726c6421

The concatenation of s1 and s2 includes the zero padding, resulting in the following value:

000000000048656c6c6f00000020776f726c6421

generate 动态创建电路

generate语句的最主要功能就是对module、reg、assign、always、task等语句或者模块进行复制

generate语句有generate_for、generate_if、generate_case三种语句

generate_for

(1)必须使用genvar申明一个正整数变量,用作for循环的判断。(genvar是generate语句中的一种变量类型,用在generate_for中声明正整数变量。)
(2)需要复制的语句必须写到begin_end语句里面。就算只有一句
(3)begin_end需要有一个类似于模块名的名字。

//格雷码转二进制
module gray2bin1 (bin, gray);   
    parameter SIZE = 8;      // this module is parameterizable    此模块可参数化
    output [SIZE-1:0] bin;    
    input  [SIZE-1:0] gray;   
    genvar i;     
    generate for (i=0; i<SIZE; i=i+1) begin:bit   
        assign bin[i] = ^gray[SIZE-1:i];   
    	end 
    endgenerate 
endmodule 

//------------------------------------------------------------------------------------//

//格雷码转二进制
module gray2bin2 (bin, gray);     
    parameter SIZE = 8;      // this module is parameterizable  
    output [SIZE-1:0] bin;  
    input  [SIZE-1:0] gray;   
    reg    [SIZE-1:0] bin;   
    genvar i;    
    generate for (i=0; i<SIZE; i=i+1) begin:bit  
        always @(gray[SIZE-1:i]) // fixed part select   固定部件选择
            bin[i] = ^gray[SIZE-1:i];    
    	end 
    endgenerate  
endmodule
//可变参数的二维的普通多位加法器
module addergen1 (co, sum, a, b, ci); 
    parameter SIZE = 4;  
    output [SIZE-1:0] sum;
    output            co;   
    input  [SIZE-1:0] a, b; 
    input             ci; 
    wire   [SIZE  :0] c;  
    wire   [SIZE-1:0] t [1:3];  
    genvar            i;  
    assign c[0] = ci;    
    // Generated instance names are:  生成的实例为:
    // xor gates: bit[0].g1 bit[1].g1 bit[2].g1 bit[3].g1 
    //            bit[0].g2 bit[1].g2 bit[2].g2 bit[3].g2
    // and gates: bit[0].g3 bit[1].g3 bit[2].g3 bit[3].g3 
    //            bit[0].g4 bit[1].g4 bit[2].g4 bit[3].g4  
    // or  gates: bit[0].g5 bit[1].g5 bit[2].g5 bit[3].g5  
    // Generated instances are connected with  
    // multi-dimensional nets t[1][3:0] t[2][3:0] t[3][3:0]  多维线网
    // (12 multi-dimensional nets total)  共12个多维线网
    generate    
        for(i=0; i<SIZE; i=i+1) begin:bit     
            xor g1 ( t[1][i],    a[i],    b[i]);  
            xor g2 (  sum[i], t[1][i],    c[i]);    
            and g3 ( t[2][i],    a[i],    b[i]);   
            and g4 ( t[3][i], t[1][i],    c[i]);   
            or  g5 (  c[i+1], t[2][i], t[3][i]);  
        end  
    endgenerate    
    assign co = c[SIZE]; 
endmodule

//可变参数的一维的普通多位加法器
module addergen1 (co, sum, a, b, ci); 
    parameter SIZE = 4;   
    output [SIZE-1:0] sum;  
    output            co;  
    input  [SIZE-1:0] a, b; 
    input             ci;   
    wire   [SIZE  :0] c;  
    genvar            i;    
    assign c[0] = ci;     
    // Generated instance names are:  
    // xor gates: bit[0].g1 bit[1].g1 bit[2].g1 bit[3].g1 
    //            bit[0].g2 bit[1].g2 bit[2].g2 bit[3].g2 
    // and gates: bit[0].g3 bit[1].g3 bit[2].g3 bit[3].g3
    //            bit[0].g4 bit[1].g4 bit[2].g4 bit[3].g4 
    // or  gates: bit[0].g5 bit[1].g5 bit[2].g5 bit[3].g5 
    // Generated instances are connected with  
    // generated nets: bit[0].t1 bit[1].t1 bit[2].t1 bit[3].t1
    //                 bit[0].t2 bit[1].t2 bit[2].t2 bit[3].t2  
    //                 bit[0].t3 bit[1].t3 bit[2].t3 bit[3].t3   
    generate     
        for(i=0; i<SIZE; i=i+1) begin:bit       
            wire   t1, t2, t3; // generated net declaration        
            xor g1 (     t1, a[i], b[i]);      
            xor g2 ( sum[i],   t1, c[i]);      
            and g3 (     t2, a[i], b[i]);     
            and g4 (     t3,   t1, c[i]);    
            or  g5 ( c[i+1],   t2,   t3);    
        end  
    endgenerate     
    assign co = c[SIZE];
endmodule 
//多层循环嵌套
parameter SIZE = 2; 
genvar            i, j, k, m;
generate  
    for (i=0; i<SIZE+1; i=i+1) begin:B1 // scope B1[i]     
        M1 N1(); // instantiates B1[i].N1[i]     
        for (j=0; j<SIZE; j=j+1) begin:B2 // scope B1[i].B2[j]    
            M2 N2(); // instantiates B1[i].B2[j].N2      
            for (k=0; k<SIZE; k=k+1) begin:B3 // scope B1[i].B2[j].B3[k]  
                M3 N3(); // instantiates实例化 B1[i].B2[j].B3[k].N3    
            end    
        end   
        if (i>0)     
            for (m=0; m<SIZE; m=m+1) begin:B4 // scope B1[i].B4[m]     
                M4 N4(); // instantiates B1[i].B4[m].N4     
            end 
    end 
endgenerate 
// some of the generated instance names are: 生成的一些实例名称包括:
// B1[0].N1  B1[1].N1  
// B1[0].B2[0].N2  B1[0].B2[1].N2 
// B1[0].B2[0].B3[0].N3  B1[0].B2[0].B3[1].N3 
//    B1[0].B2[1].B3[0].N3  
// B1[1].B4[0].N4  B1[1].B4[1].N4

generate_if

generate_for用于复制模块,而generate_if则是根据模块的参数(必须是常量)作为条件判断,来产生满足条件的电路。相当于判断语句。

//一种参数化乘法器模块的实现
module multiplier(a,b,product);
    parameter a_width = 8, b_width = 8; 
    localparam product_width = a_width+b_width;// can not be modified  不能修改
    // directly with the defparam statement 直接使用defparam语句
    // or the module instance statement # 或使用模块实例中的#()语句修改
    input    [a_width-1:0]    a; 
    input    [b_width-1:0]    b;
    output   [product_width-1:0]    product; 
	generate   
        if((a_width < 8) || (b_width < 8))    
            CLA_multiplier #(a_width,b_width) u1(a, b, product);  
        // instance a CLA_multiplier   实例化
        else    
            WALLACE_multiplier #(a_width,b_width) u1(a, b, product);   
        // instance a Wallace-tree  multiplier 实例化
    endgenerate
    // The generated instance name is u1 生成实例名u1
endmodule

generate_case

generate_case其实跟generate_if一样,都是根据参数(都必须为常量)作为判断条件,来产生满足条件的电路,不同于使用了case语法而已。

generate   
    case (WIDTH)   
    1:  adder_1bit x1(co, sum, a, b, ci); // 1-bit adder implementation   
    2:  adder_2bit x1(co, sum, a, b, ci); // 2-bit adder implementation    
    default: adder_cla #(WIDTH) x1(co, sum, a, b, ci); // others - carry look-ahead adder
    endcase // The generated instance name is x1 
endgenerate

/*---------------------------------------------------------------------------------------------------*/
module	generate_case(
	input t0 ,
	input t1 ,
	input t2 ,
	output d			
);
	localparam    S = 8;	            //定义模块所需参数,用于判断产生电路

	generate 
		case(S)
		0:assign d = t0 | t1 | t2;
		1:assign d = t0 & t1 & t2;
		default:assign d = t0 & t1 | t2;
		endcase
	endgenerate
endmodule

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

defparam高层改低层参数

​ 方法一:引用实例时对实例内的参数进行改变

在引用Decode实例时,D1,D2的Width将采用不同的值4和5,且D1的Polarity将为0。可用例
子中所用的方法来改变参数,即用 #(4,0)向D1中传递 Width=4,Polarity=0; 用#(5)向D2中传递
Width=5,Polarity仍为1。

传参按顺序传入

module Decode(A,F);
	parameter Width=1, Polarity=1;
	……………
endmodule

module Top();
	wire[3:0] A4;
	wire[4:0] A5;
	wire[15:0] F16;
	wire[31:0] F32;
	Decode #(4,0) D1(A4,F16);
	Decode #(5) D2(A5,F32);
Endmodule

不按顺序,直接使用defparam修改

module foo(a,b);  
    real r1,r2;  
    parameter [2:0] A = 3’h2;  
    parameter B = 3’h2;   
    initial
        begin   
            r1 = A;   
            r2 = B;
     		$display("r1 is %f r2 is %f",r1,r2);   
        end
endmodule // foo 



module bar;  
    wire a,b;   
    defparam f1.A = 3.1415;  
    defparam f1.B = 3.1415;  
    foo f1(a,b); 
endmodule // bar

方法二:通过defparam直接在高层模块中修改

多层次模块构成的电路,在一个模块中改变另一个模块的参数时,需要使用defparam命令

module Test;
	wire W; 
	Top T ( );
endmodule

module Top;
    wire W ;
    Block B1 ( ); 
    Block B2 ( ); 
	endmodule

module Block;
    Parameter P = 0; 
endmodule

module Annotate; 
    defparam  
    	Test.T.B1.P = 2,   
    	Test.T.B2.P = 3;
	endmodule

port 端口的定义

module test(a,b,c,d,e,f,g,h); input [7:0] a;
    // no explicit declaration - net is unsigned   没有显式声明-net是无符号的
    input [7:0] b;   
    input signed [7:0] c;   
    input signed [7:0] d; // no explicit net declaration - net is signed   没有显式的net声明-net被签名
    output [7:0] e; // no explicit declaration - net is unsigned   没有显式声明-net是无符号的
    output [7:0] f; 
    output signed [7:0] g;  
    output signed [7:0] h; // no explicit net declaration - net is signed  没有显式的net声明-net被签名
    wire signed [7:0] b;   // port b inherits signed attribute from net decl.  端口b从net decl继承signed属性。
    wire [7:0] c; // net c inherits signed attribute from port   net c从端口继承signed属性
    reg signed [7:0] f;  
    // port f inherits signed attribute from reg decl.   端口f从reg decl继承signed属性。
    reg [7:0] g; // reg g inherits signed attribute from port  net g从端口继承signed属性
endmodule 


//===============================================不懂,没百度到===================================================
module complex_ports ({c,d}, .e(f));  
    // Nets {c,d} receive the first port bits.   net{c,d}接收第一个端口位。
    //Name ’f’ is declared inside the module.    名称“f”在模块内声明。        
    // Name ’e’ is defined outside the module.     名称“e”在模块外部定义          
    // Can’t use named port connections of first port.   无法使用第一个端口的命名端口连接
    
    module split_ports (a[7:4], a[3:0]);   
      // First port is upper 4 bits of ’a’.    第一个端口是“a”的高位4位。             
      // Second port is lower 4 bits of ’a’.        第二个端口是“a”的低4位。          
      // Can’t use named port connections because of part-select port ’a’.  无法使用命名端口连接,因为部分选择端口“a”
        
module same_port (.a(i), .b(i));      
    // Name ’i’ is declared inside the module as a inout port. 名称“i”在模块内声明为inout端口。为
    // Names ’a’ and ’b’ are defined for port connections.  端口连接定义了名称“a”和“b”。
    
    
module renamed_concat (.a({b,c}), f, .g(h[1]));                  
    // Names ’b’, ’c’, ’f’, ’h’ are defined inside the module.   名称“b”、“c”、“f”、“h”在模块内定义          
    // Names ’a’, ’f’, ’g’ are defined for port connections.   为端口连接定义了名称“a”、“f”、“g”。          
    // Can use named port connections.  可以使用命名端口连接。
  //============================================================================================================
   
    
    module same_input (a,a); input a;        
        // This is legal. The inputs are ored together. 这是合法的。输入是“或”在一起的。

verilog提供signed(有符号数)和unsigned(无符号数)两种运算

Unsigned:不含sign bit(符号位)
	以4bit的数据来说,范围为0000 ~ 1111,即0 ~ 15
Signed:含sign bit(符号位)
	以4bit的数据来说,范围为1000 ~ 0111,即-8 ~ +7 (有符号数用补码来表示)

unsigned运算时,如果发生高位溢出,会舍去溢出的数,如1111+1=(1)0000.

signed运算时,要考虑符号https://www.cnblogs.com/oomusou/archive/2009/10/31/verilog_signed_overflow.html

The real data type shall not be directly connected to a port. It shall be connected indirectly, as shown in the following example. The system functions $realtobits and $bitstoreal shall be used for passing the bit patterns across module ports.

real类型不应直接连接到端口,应间接连接。如下例所示。系统功能 r e a l t o b i t s 和 realtobits和 realtobitsbitstoreal应用于在模块端口之间传递位模式

real 实数寄存器 realtime 实数时间寄存器

https://blog.csdn.net/u011731939/article/details/40807449

Hierarchical names分层名称

module mod (in); 
    input in; 
    reg hold; 
    always @(posedge in) begin : keep 
        hold = in;
    end
endmodule


module cct (stim1, stim2);
    input stim1, stim2;
// instantiate mod 实例化mod模块
    mod amod(stim1), bmod(stim2);  
endmodule 

module wave;
    reg stim1, stim2;
    cct a(stim1, stim2); // instantiate cct 实例化cct模块
    initial begin :wave1
        #100 fork :innerwave
            reg hold; 
        join 
        #150 begin 
            stim1 = 0;
        end
    end 
endmodule

有如图结构
在这里插入图片描述

a list of the hierarchical forms of the names of all the objects defined in the code

代码中定义的所有对象名称的层次结构列表

在这里插入图片描述

Scope rules变量的搜索规则

错误操作:

在同一模块中声名两个相同的变量,

在同一模块中任务或函数声名名称相同,

为门实例指定与连接到其输出的网络的名称相同的名称

向上搜索原则(无层次路径)

如果在任务、函数或命名块中直接引用标识符(无层次路径),则向上搜索。

先在本范围(任务,函数或命名块等),没找到则继续向外部搜索标识符,搜索完模块或搜索到标识符为止。注意:不搜索同级范围

有层次路径

如果一个标识符引用了一个分层名称,那么路径可以以模块名、实例名、任务、函数或命名块开头。应首先在当前级别搜索名称,然后在更高级别的模块中搜索,直到找到为止。由于模块名和实例名都可以使用,所以如果有一个名为与实例名相同的模块,则实例名优先。

猜你喜欢

转载自blog.csdn.net/qq_45704265/article/details/108167238