verilog基础语法之数据类型

   Verilog最常用的数据类型有两种:线网(wire)和寄存器(reg)。其中,wire 类型表示硬件单元之间的物理连线,reg用来表示存储单元。

1、 wire类型

   wire类型是信号在不同元器件之间传递的媒介,用于表示硬件电路单元之间的物理连线,由其连接的器件的输出端连续驱动。如果没有驱动元件连接到wire型变量,或者存在冲突的驱动(即多个驱动源同时驱动同一个wire),那么该变量的值默认为"High-Impedance"(高阻态),通常表示为"Z"。高阻态是一种不驱动信号的状态,相当于该信号线上没有电流流动。“驱动”是指信号源对连线施加的电平,这个信号源可以是一个逻辑门、触发器、缓冲器、驱动元件或者任何其他可以产生信号的硬件实体。
   另外,wire型变量的值可以由连续赋值(使用=操作符)或非阻塞赋值(在always块中使用<=操作符)决定。连续赋值类似于组合逻辑,它描述了输入变量和输出变量之间的直接关系,而输出值会随着输入值的变化而立即变化。
示例:

wire signal_wire; // 声明一个wire类型的信号线
assign signal_wire = some_driver; // some_driver是一个驱动源,可以是门、触发器等

在这个例子中,assign语句定义了一个连续赋值,some_driver是驱动signal_wire的驱动源。如果some_driver是一个逻辑门的输出,那么signal_wire将根据该逻辑门的输入而变化。

wire gnd = 1'b0;//创建一个名为 gnd 的全局地线信号,它被赋予了一个逻辑0(二进制值0)的初始值,地线通常在电路中表示参考点或0电平。

这行代码定义了一个名为 gnd 的 wire 类型的信号,并初始化为逻辑值 0。在某些情况下,设计者可能会使用 wire 类型来定义一个常量,即使用 wire 来表示一个始终为特定值的信号,但更常见的做法是使用 parameter 或 localparam 关键字来定义常量。对于地线,一般不需要在代码中显式定义,因为地线通常在FPGA的物理设计中是预定义的,并在布局时连接到相应的电源和地引脚。

   需要特别说明的是,wire型变量通常用于表示模块的端口或者作为信号的传递媒介。它们不应当在always块内部被赋值,因为wire代表着连线,其值由外部信号源决定,而非由always块内的逻辑产生。如果试图在always块中对wire型变量使用<=操作符,这将导致编译错误,因为wire不允许在always块内部赋值。 然而,wire型变量可以在always块中被用作非阻塞赋值表达式中的一个源(source),但这只出现在一个模块的输出端口被另一个模块的输入端口所驱动的情况下。在这种情况下,wire实际上是连接两个模块的信号线。

   以下是一个简单的示例,演示了如何在模块间使用wire型变量进行非阻塞赋值:

module d_flip_flop(
    input wire clk,       // 时钟信号
    input wire data_in,   // 数据输入
    output reg data_out  // 数据输出
);`在这里插入代码片`

// 使用非阻塞赋值在时钟上升沿捕获data_in的值
always @(posedge clk) begin
    data_out <= data_in;
    end

endmodule

// 测试模块,实例化d_flip_flop
module testbench();
    wire clk;
    wire data_in;
    wire data_out;

    // 实例化d_flip_flop模块
    d_flip_flop u_d_flip_flop(
        .clk(clk),
        .data_in(data_in),
        .data_out(data_out)
    );

    // 驱动测试信号
    initial begin
        clk = 0;
        forever #10 clk = ~clk; // 产生时钟信号
    end

    initial begin
        data_in = 0;
        #20 data_in = 1; // 在时间20ns处改变输入数据
        #20 data_in = 0;
    end

    // 监视输出变化
    initial begin
        $monitor("Time = %t, clk = %b, data_in = %b, data_out = %b", $time, clk, data_in, data_out);
    end
    
endmodule

在这个例子中,data_out是一个reg型变量,它在d_flip_flop模块的always块中使用非阻塞赋值从data_in获得值。clk和data_in是wire型变量,它们在测试模块testbench中被驱动,并且连接到d_flip_flop模块的相应端口。请注意,尽管data_out是reg类型并且可以使用非阻塞赋值,但data_in和clk作为wire类型,它们的值是由测试模块生成的信号所驱动的,而不是在d_flip_flop模块内部的always块中赋值。在这个示例的always块中,data_in的值在时钟边沿被采样,并在data_out中保持,直到下一个时钟边沿到来。

总结来说,在Verilog中,“驱动”指的是信号源对连线施加的电平,而驱动源是产生这些信号的任何硬件元件。如果没有驱动源,wire型变量将呈现高阻态"Z"。

2、 reg类型

   reg用来表示存储单元,它是一种可以存储数据并保持其状态的硬件元素。在仿真环境中,reg类型的变量行为与实际硬件中的寄存器类似,用于模拟寄存器的行为。在硬件实现中,reg声明的变量将被映射到FPGA或ASIC中的相应寄存器结构。与wire不同,reg不是用于连接模块的物理线,而是用于表示可以存储状态的寄存器。以下是reg类型的一些关键特性和用法:

  • 状态保持:reg类型的变量可以保持它们的值,直到它们被新的赋值语句更新。这种特性使得reg类型非常适合用于建模需要记忆先前值的硬件寄存器和触发器。

  • 非阻塞赋值:reg类型的变量通常与非阻塞赋值(使用 <=操作符)一起使用,这在时序逻辑中非常重要。非阻塞赋值确保了多个寄存器可以在同一时钟边沿更新,而不会产生竞态条件。

  • 时序控制:在always块中,当指定了时钟信号(例如 posedge clk 或 negedgeclk),reg变量的赋值将与时钟信号的边沿同步。

  • 初始化:可以在声明时初始化reg变量,但这种初始化仅在仿真开始时有效,实际硬件实现中寄存器的初始状态取决于其物理实现或配置过程。

  • 并发与顺序:reg变量可以用于顺序逻辑(在always块中)和并

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值