Menu Close

Verilog 变量声明与数据类型一

Verilog语法中最基本的数据类型有 线网(wire),寄存器(reg)和整数(integer)三种类型,这三种数据类型是可综合的数据类型,在Verilog 程序设计中被广泛使用。其它还有可以用于仿真的数据类型如 timer,real,字符串等变量都可以看作reg类型的扩展。wire,reg ,integer,timer,real是声明变量类型的关键字。变量必须先声明后使用,声明后变量的数据类型也就确定了。变量声明是模块(module)内惟一的,不能在同一个模块或函数内重复声明。

1.线网(wire):

线网(wire)类型表示逻辑单元或实例之间的连线,一般由逻辑单元的输出驱动。没有连接驱动的wire型变量的值为高阻’z’。

  • wire类型变量的使用:
    • wire型变量的声明与赋值

wire类型的变量只能由assign语句赋值,或在声明时赋初值。而且赋值的机会只有一次。

变量声明实例:

wire    a, b;  
wire    c = 0;
wire    d = 1'b1;
assign  a = c;

 

声明a, b为线网类型,并将c的值赋给a, 此时a的值为0;而且a只有这一次赋值机会。

变量c在声明的时候赋初值为0,此后c就一直保留该值,不能再给c赋值,也不能再次声明。

注意:wire类型的变量不能重复赋值。

    • 桥接

Wire 型变量作为中间变量可以实现桥接的作用。在下面的例子中可以看出,wire型变量起到变量之间值传递的作用。

实例1:

module  wire_bridge
(
    input  a,b,ci,
    output y,co
);
 
wire   d, e, f;
  
assign d = a ^ b;
assign e = a & b;
assign f = ci & d;
assign y = d ^ ci;
assign co = e | f;
  
endmodule

 

wire变量在逻辑电路中的对应关系,简单的说就是起到连线的作用。

在例化模块之间传递变量。

实例2:

module  fadder4
(
    input  ci,
    input  [3:0] a,
    input  [3:0] b,
 
    output [3:0] y,
    output co
);
 
wire  co1,co2,co3;
 
// 例化 一位全加器,并重复使用4次
fadder1   fadder1_inst1
(
    .ci (ci),
    .a  (a[0]),
    .b  (b[0]),
    .y  (y[0]),
    .co (co1)
);
 
fadder1   fadder1_inst2
(
    .ci  (co1),
    .a   (a[1]),
    .b   (b[1]),
    .y   (y[1]),
    .co  (co2)
);
 
fadder1   fadder1_inst3
(
    .ci  (co2),
    .a   (a[2]),
    .b   (b[2]),
    .y   (y[2]),
    .co  (co3)
);
 
fadder1   fadder1_inst4
(
    .ci  (co3),
    .a   (a[3]),
    .b   (b[3]),
    .y   (y[3]),
    .co  (co)
);
 
endmodule

 

wire型变量只能在并发语句或例化模块中被赋值,如实例1中的 d、e、f 和实例2中co1、co2、co3; 但wire型变量可以根据需要在并发语句或顺序语句中赋值给其他变量。

对wire型变量有以下几种赋值方式:

  • 使用assign语句
  • 变量定义
  • 例化模块的输出

注意:wire型变量不能在顺序语句中被赋值。

寄存器(reg )类型:

寄存器(reg)是一种具有记忆功能的数据类型。用来表示存储单元,它会保持数据原有的值,直到被改写。一般分为锁存器和触发器两种。但无论哪一种建模,它们都只能在顺序语句中被赋值,而不能在并发语句中赋值。

例:

reg a;
reg b;

always@(*)
begin
    a <= 1'b1;
    b <= 1'b0;
end

 

而 assign a = 1’b1; 就是错误的;因为a是reg型变量。

与wire类型变量不同的是,在reg型变量声明时可以赋初值,而后续的顺序语句可以对该变量继续赋值,从而修改原值。而wire型变量只有一次赋值机会。

注意:在同一个顺序过程语句中可以对reg型变量多次赋值,后面的赋值会替代前面的赋值,充分利用这一特点,可以使程序更简洁。但不允许在多个顺序过程语句中对同一个reg型变量都赋值。

 

module reg_assign
(
    input   clk,
    input   a,
    input   b,

    input   sel,
    output  c
);

reg ma;

//顺序过程语句1
always @(posedge clk)
begin
    if(sel)
        ma <= a;
end

//顺序过程语句2
always @(posedge clk)
begin
    if(!sel)
        ma <= b;
end


assign c = ma;

endmodule


上面的例子红色部分是有问题的,虽然reg 型变量允许被多次赋值,但不能在不同的顺序过程中多次赋值。上面的代码可以修改如下:

module reg_assign
(
    input  clk,
 
    input  a,
    input  b,
 
    input  sel,
    output c
);
 
reg    ma;
 
//顺序过程语句1
always @(posedge clk)
begin
    if(sel)
        ma <= a;
    else
        ma <= b;
end
 
assign c = ma;
 
endmodule

 

wire型变量与reg型变量都可以使用向量(vector)进行声明;

如 : wire [3:0] a, b;

reg [3:0] c, d;

向量的运算遵循运算符的规则,细节参见verilog 运算符。

 

对应视频:

Posted in FPGA, FPGA 教材教案, Verilog, Verilog, 教材与教案, 文章

4 Comments

  1. wangff

    学习本篇文章后有几点收获,1、三种基本类型:线网(wire)、寄存器(reg)、整数(integer);2、wire型变量只有一次赋值机会;3、reg型变量不能在不同的顺序过程语句中被多次赋值;
    本篇文章围绕wire、reg型变量的声明、赋值等知识展开讲解,举例论证非常充分,并对初学者容易出现的错误问题,做了重点讲解,相信每一位初学者阅读后都会受益匪浅!

发表回复

相关链接