【学习笔记】Verilog之四:结构建模方法

简介: Verilog 提供两种建模方法:行为建模和结构建模。行为建模专注于电路功能描述,类似高级编程语言,不涉及底层实现。数据流建模使用 `assign` 进行连续赋值,适合描述组合逻辑。线网可以在声明时直接赋值。顺序行为建模通过 `initial` 和 `always` 语句实现,`initial` 用于一次性初始化,`always` 则用于响应特定事件的重复执行。时序控制包括时延和事件控制,用于精确控制电路行为。阻塞和非阻塞赋值决定了语句执行的顺序和并发性。过程性连续赋值如 `assign-deassign` 和 `force-release` 提供了更多灵活性。

Verilog 提供两种主要的建模方法:行为建模和结构建模。结构建模聚焦于电路的具体物理结构描述,而行为建模则侧重于电路功能的描述,类似于高级编程语言的风格,如C语言,不涉及底层实现细节。

3.1 数据流行为建模

数据流建模是一种简洁的行为建模方式,核心在于使用assign关键字进行连续赋值,适用于描述组合逻辑电路。

连续赋值语句
  • 语法:assign LHS_target = RHS_expression;
  • LHS_target: 目标线网
  • RHS_expression: 赋值操作表达式

示例:

Verilog

wire[3:0] z, preset, clear;
assign z = preset & clear;
  • 赋值目标: 包括标量线网、向量线网、向量的位选择、向量的部分选择及这些类型的连接结果。
  • 执行机制: 右侧操作数变化时,表达式重新计算并将新结果赋给左侧线网。
  • 时延: 支持上升时延、下降时延和关闭时延,语法为assign #(rise, fall, turn-off) LHS_target = RHS_expression;
线网声明赋值

线网可在声明时直接赋值,例如:

Verilog

wire[3:0] sum = 4'b0;

时延的概念

  • 时延: 定义程序暂停的单位时间长度,默认时延为0。
  • 线网时延: 时延可内置于线网声明中,用于控制赋值的时机。

数据流建模实例:一位全加器

使用数据流建模方式实现一位全加器,可以直观展示连续赋值语句的使用。

Verilog

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

在这个例子中,abcin是输入,sumcout是输出。sum是半加器的输出,而cout是进位输出,通过连续赋值语句assign直接计算得出。





3.2 语句块


3.2.1 顺序行为建模:Initial与Always语句

在Verilog的顺序行为描述中,initialalways语句是构建动态逻辑行为的核心。它们不仅限于单一语句,而是引导了一系列的过程或结构,允许更复杂的控制流和时序逻辑的描述。

Initial语句

  • 执行时机:仅执行一次,在仿真启动的瞬间(时刻0)。
  • 封装结构:通常采用begin-end块封装多条语句,形成顺序执行的语句块。
  • 局部变量:若语句块中使用局部变量,如integer Index;,则需命名该语句块。

示例:

Verilog

parameter SIZE = 1024;
reg[7:0] RAM [0:SIZE-1];
reg RibReg;

initial begin: SEQ_BLK_A
   integer Index;
   RibReg = 0;
   for (Index = 0; Index < SIZE; Index = Index + 1)
       RAM[Index] = 0;
end

Always语句

  • 执行时机:从时刻0开始,依据时序控制条件重复执行。
  • 时序控制:通过@符号定义事件触发或使用wait关键字定义电平敏感事件。
  • 执行模式:与initial不同,always可根据条件多次触发执行。

语法格式:

Verilog

1always [timing_control] procedural_statement

其中,

  • timing_control:时序控制,可为时延控制或事件控制。
  • procedural_statement:过程语句,描述具体的逻辑行为。

示例:

Verilog

always @(posedge clk or negedge rst)
    if (!rst)
        Q <= 1'b0;
    else
        Q <= D;

小结

在Verilog设计中,initialalways语句是实现顺序行为建模的关键工具。initial语句适用于一次性初始化,而always语句则用于响应特定事件或条件的重复执行,两者结合提供了灵活的时序逻辑描述能力。通过适当的封装和时序控制,可以精确控制电路的动态行为,满足复杂逻辑设计的需求。






3.2.2 时序控制

时序控制是Verilog中用于精确控制电路行为的重要机制,主要包括时延控制事件控制两大类。

时延控制

时延控制允许在指定的时间间隔后执行操作,主要形式包括:

  • 语句前时延
  • 单独时延
  • 语句内时延

示例

Verilog

Done = #5 (A & B);

等价于:

Verilog

begin
    tmp = (A & B);
    #5 Done = tmp;
end

值得注意的是,显示零时延(#0)将导致当前仿真时间点的执行挂起,直到所有同时发生的事件处理完毕。

事件控制

事件控制通过监测特定事件的发生来触发操作,分为边沿触发事件电平敏感事件

边沿触发事件

使用@符号定义,可监测一个或多个事件,多个事件间使用or关键字分隔。

示例

Verilog

always @(posedge clk or negedge rst)
    if (!rst)
        Q <= 1'b0;
    else
        Q <= D;
电平敏感事件

使用wait关键字定义,等待条件满足后执行后续过程。

示例

Verilog

wait (condition);
    // process statements

其中,condition定义了电平敏感事件的触发条件。

小结

通过时延控制和事件控制,Verilog提供了丰富的机制来精确控制电路的时序行为。无论是简单的时延操作,还是复杂的边沿触发和电平敏感事件,都能有效地模拟和控制电路的动态特性。理解并熟练运用这些时序控制机制,是Verilog设计中不可或缺的一部分。





3.2.3 Verilog中的语句块与赋值机制


在Verilog中,语句块分为两类:顺序语句块和并行语句块,分别用于控制语句的执行顺序和并行度。

  1. 顺序语句块:使用begin-end结构,确保语句按顺序执行。
  2. 并行语句块:使用fork-join结构,使语句块中的语句并行执行,不依赖于书写顺序。

过程性赋值

过程性赋值是Verilog中最常用的赋值形式,特点如下:

  • 出现在initialalways语句中。
  • 专用于寄存器变量赋值。
  • 右侧表达式可以是任意类型。

过程性赋值分为阻塞和非阻塞两种:

  1. 阻塞过程赋值:使用=操作符,执行赋值时会阻塞后续语句。
  2. 非阻塞过程赋值:使用<=操作符,赋值与后续语句并行执行。

混合使用阻塞与非阻塞赋值

在Verilog设计中,阻塞与非阻塞赋值的混合使用是常见的,需要根据设计需求和性能考虑来决定。

过程性连续赋值

不同于标准的连续赋值,过程性连续赋值结合了过程赋值的灵活性和连续赋值的响应性,支持对寄存器和线网赋值。

  • assign-deassign:用于寄存器赋值,assign赋值,deassign取消赋值。
  • force-release:用于线网和寄存器的强制赋值和释放,force覆盖当前值,release恢复原状。

示例代码

以下示例代码,展示assign-deassignforce-release的使用:

Verilog

module DEF(D, Clr, Clk, Q);
    input D, Clr, Clk;
    output Q;
    reg Q;

    always @(negedge Clk)
        Q = D;

    always @(Clr)
        if (!Clr) begin
            assign Q = 0;
        end else begin
            deassign Q;
        end
endmodule


// Force-release example
module ForceRelease(Colt);
    reg[2:0] Colt;
    wire prt;
    or #1 (prt, Std, Dzx); // Or gate definition

    initial begin
        Colt = 2;
        force Colt = 1;
        release Colt;
        assign Colt = 5;
        force Colt = 3;
        release Colt;
    end

    initial begin
        force prt = Dzx & Srd;
        #5;
        release prt;
    end
endmodule


以上代码展示了assign-deassignforce-release的使用,以及如何通过fork-joinbegin-end块来控制语句的执行顺序和并行性。通过这些机制,Verilog提供了强大的手段来描述和控制电路行为。




3.2.5 If语句

If语句用于条件分支控制,如果一个分支包含多条过程语句,应使用begin-end块将其包裹,类似于C语言中的大括号{}



3.2.6 Case语句

Case语句用于多路分支选择,特别指出的是,当条件表达式或分支表达式中的某些位出现未知值x或高阻态z时,这些值在比较中仍具有意义,只要在相同位置出现xz,就被视为相等。

  • casex和casezcasex和casez语句提供了特殊处理xz的方式:
  • casez:在比较中,值z被视为无关值,即在该位出现z时,该位在比较中被忽略。
  • casex:值xz都被视为无关位,只要其余位匹配,即认为两个值相等。



3.2.7 循环语句

循环语句允许重复执行一组过程语句,Verilog提供了多种循环控制结构。

  1. forever循环
    forever循环持续不断地执行过程语句,无需声明循环变量。其语法格式为:
  2. Verilog
forever
    procedural_statement
  1. 注意:forever循环中必须包含时序控制,否则将在0时延后无限循环。forever循环常用于生成周期性波形,作为仿真测试信号。
  2. repeat循环
    repeat循环执行固定次数的过程语句,通过loop_count控制循环次数。语法格式如下:
  3. Verilog
repeat(loop_count)
    procedural_statement
  1. loop_count为不确定值(如xz),则循环次数被视为0。
    示例
  2. Verilog
repeat(Count) @ (posedge Clk) Sum <= Sum + 1;
  1. 此示例中,首先计算Sum + 1的值,然后等待Clk的上升沿,最后执行赋值操作。
  2. while循环
    while循环在条件为真时重复执行过程语句,直至条件变为假。
  3. for循环
    for循环提供了一种结构化的循环控制,包括初始化、条件检查和循环变量更新三个部分。

示例代码

以下示例代码,展示了Verilog中的控制结构使用:

Verilog

module ControlStructures(
    input wire clk,
    input wire reset,
    output reg [3:0] counter
);

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            counter <= 4'b0;
        end else begin
            if (counter == 4'b1111) begin
                counter <= 4'b0;
            end else begin
                counter <= counter + 1;
            end
        end
    end

    always @(counter) begin
        case(counter)
            4'b0000: output <= "Zero";
            4'b0001: output <= "One";
            4'b0010: output <= "Two";
            default: output <= "Other";
        endcase
    end

    initial begin
        forever #10 counter <= counter + 1;
    end

    always @(counter) begin
        repeat(4) @(negedge clk);
    end

endmodule

以上代码展示了if语句、case语句、forever循环以及repeat循环的使用,体现了Verilog中控制结构的多样性和灵活性。



相关文章
|
3月前
|
设计模式
建模底层逻辑问题之以命令设计模式为例,要用定义法建模,如何实现
建模底层逻辑问题之以命令设计模式为例,要用定义法建模,如何实现
|
5月前
|
网络协议 网络性能优化 数据安全/隐私保护
计算机网络基础知识和术语(二)---分层结构模型
计算机网络基础知识和术语(二)---分层结构模型
75 1
|
5月前
|
开发框架 监控 .NET
【学习笔记】Verilog之三:行为建模方法
Verilog是一种硬件描述语言,用于模拟电子系统的结构和行为。行为建模是Verilog的一种方法,分为数据流行为建模和顺序行为建模。 数据流行为建模主要使用`assign`语句,它描述了电路的功能而不涉及具体结构。连续赋值语句(`assign`)用于给线网分配值,当右端表达式发生变化时,新值会立即赋给线网。此外,还有时延的概念,可以指定赋值或事件发生的延迟时间。
|
5月前
|
监控 算法 数据处理
【学习笔记】Verilog之五:任务、函数及其他
在Verilog HDL中,任务(tasks)和函数(functions)增强了代码的可读性和重用性。任务是仅在仿真环境中使用的可封装代码,不可综合为硬件电路。任务定义包括标识符、输入/输出声明和实现代码,调用时需提供参数列表。函数与任务类似,但返回单个值,不包含时序控制,并且可以互相调用。函数定义包括返回值范围、输入声明、变量声明和执行代码。系统任务和函数如 `$display` 和 `$fopen` 提供了显示信息、文件I/O等便利功能,用于仿真控制和调试。禁止语句和命名事件则帮助控制代码执行和事件同步。
|
芯片 异构计算
第三章 硬件描述语言verilog(三)功能描述-时序逻辑
第三章 硬件描述语言verilog(三)功能描述-时序逻辑
260 0
第三章 硬件描述语言verilog(三)功能描述-时序逻辑
|
定位技术
定义系统、模型、结构等概念|认知建模笔记翻译(4)
定义系统、模型、结构等概念|认知建模笔记翻译(4)
120 0
|
算法 C语言 图形学
labview编程笔记之条件结构
labview编程笔记之条件结构
458 0
labview编程笔记之条件结构
|
数据可视化 测试技术 uml
【UML建模】(1) UML建模的初了解,概述,组成,作用
UML (Unified Modeling Language)是一种通用的可视化的建模语言,可以用来描述、可视化、构造和文档化软件密集型系统的各种工件。它不是一种程序设计语言。 UML 是独立于过程的,它可以在软件生命周期的各个阶段运用,不过主要应用于软件开发的设计与分析阶段。
454 0
【UML建模】(1) UML建模的初了解,概述,组成,作用
|
安全 前端开发 测试技术
SystemVerilog学习-01-系统验证概述(一)
SystemVerilog学习-01-系统验证概述
328 0
SystemVerilog学习-01-系统验证概述(一)
|
监控 安全 搜索推荐
SystemVerilog学习-01-系统验证概述(二)
SystemVerilog学习-01-系统验证概述
400 0
SystemVerilog学习-01-系统验证概述(二)