liehuf-notes liehuf-notes
首页
K230
Verilog
留言板
我的博客 (opens new window)
GitHub (opens new window)
首页
K230
Verilog
留言板
我的博客 (opens new window)
GitHub (opens new window)
  • 01.VerilogHDL的坤本素养
  • 02.VerilogHDL程序设计和描述方式
    • 一、数据流建模
    • 二、行为级建模
    • 三、 结构化建模是啥?
      • 总结
    • 三种建模方式对比
  • Verilog
猎户f
2025-07-12
目录

02.VerilogHDL程序设计和描述方式

# Verilog HDL程序设计

# 一、数据流建模

# 1. 数据流建模是啥?

核心思想:用“电线连接”的方式描述电路,直接表示信号如何从输入流动到输出。 类比:就像画电路图,用导线把各个元件连起来,比如 A和B接个与门,输出Y。

# 2. 核心工具:连续赋值语句(assign)

作用:告诉Verilog“这根线(wire)的值等于某个表达式的结果”。

# 2.1 显式连续赋值
  • 语法:

    wire Y;          // 先声明线网
    assign Y = A & B; // 再用assign赋值
    
    1
    2
  • 带延迟的例子:

    assign #3 Y = A & B; // 计算A&B后,延迟3个单位时间再赋值给Y
    
    1
# 2.2 隐式连续赋值
  • 语法(声明时直接赋值):

    wire Y = A & B;      // 声明时直接赋值
    wire #(2,3,4) Z = X; // 带延迟(上升2,下降3,关断4)
    
    1
    2
  • 带驱动强度的例子:

    wire (strong1, weak0) Y = A | B; // 输出1时强驱动,0时弱驱动
    
    1

# 3. 连续赋值的特点

  1. 目标必须是wire:

    • 不能给reg类型赋值!

    • 示例:

      wire Y;    // 正确
      reg Y;     // 错误!assign不能用于reg
      assign Y = A;
      
      1
      2
      3
  2. 实时更新:

    • 只要右边的信号(如A或B)变化,立刻重新计算并赋值。

    • 示例:

      assign Y = A + B; // A或B一变,Y立刻更新
      
      1
  3. 并行执行:

    • 所有assign语句同时工作,和代码顺序无关。

    • 示例:

      assign Y = A & B;
      assign Z = C | D; // 这两行并行执行
      
      1
      2
  4. 延迟是“惯性延时”:

    • 短于延迟的脉冲会被过滤掉。

    • 示例:

      assign #5 Y = A; // 如果A的脉冲宽度<5,Y不会变化
      
      1

# 4. 实际代码示例

# 4.1 显式赋值(带延迟)
module example1(input [3:0] A, B, output [3:0] Y);
  wire [3:0] Y;
  assign #(3,2,4) Y = A & B; // 上升延迟3,下降2,关断4
endmodule
1
2
3
4
# 4.2 隐式赋值(带驱动强度)
module example2(input [3:0] M, N, output [3:0] W);
  wire (strong0, weak1) [3:0] W = (M ^ N) & (M | N);
endmodule
1
2
3

# 5. 常见问题

  1. 什么时候用连续赋值?

    • 描述组合逻辑(如与门、加法器、多路选择器)。
    • 不适合时序逻辑(如触发器要用always块)。
  2. 忘记写assign会怎样?

    • 直接写 wire Y = A; 是隐式赋值,合法。

    • 但分开写时漏掉assign会报错:

      wire Y;
      Y = A; // 错误!缺少assign
      
      1
      2
  3. 能用在always块里吗?

    • 不能! assign是并行语句,always是过程块,两者不兼容。

# 二、行为级建模

# 1. 行为级建模是啥?

核心思想:用"软件思维"描述硬件行为,重点关注电路做什么(功能),而不是具体怎么连线。 类比:就像写剧本告诉演员怎么演,而不是设计舞台的每个螺丝钉。

# 2. 核心工具:过程块(always/initial)

# 2.1 initial块 - 一次性剧本
  • 特点:只执行一次,主要用于仿真初始化。

  • 示例:

    initial begin
      clk = 0;      // 初始时钟为0
      reset = 1;    // 复位信号置1
      #50 reset = 0;// 50单位时间后取消复位
    end
    
    1
    2
    3
    4
    5
# 2.2 always块 - 循环剧本
  • 特点:不断重复执行,是硬件行为的核心描述方式。

  • 敏感列表:决定何时触发:

    // 组合逻辑:输入变化就执行
    always @(a or b or sel) 
    
    // 时序逻辑:时钟边沿触发
    always @(posedge clk)
    
    1
    2
    3
    4
    5

# 3. 过程赋值:硬件界的"变量赋值"

# 3.1 阻塞赋值(=) - 顺序执行
  • 特点:像普通编程语言,一步完成计算和赋值。

  • 适用场景:组合逻辑设计。

  • 示例:

    always @(a or b) begin
      temp = a & b;  // 立即计算并赋值
      y = temp | c;  // 使用更新后的temp
    end
    
    1
    2
    3
    4
# 3.2 非阻塞赋值(<=) - 并行执行
  • 特点:先计算右边,等时间步结束才统一赋值。

  • 适用场景:时序逻辑设计(触发器)。

  • 示例:

    always @(posedge clk) begin
      q1 <= d;   // 这三个赋值
      q2 <= q1;  // 是同时进行的
      q3 <= q2;  // 构成移位寄存器
    end
    
    1
    2
    3
    4
    5

# 4. 流程控制:硬件版的"if-else"

# 4.1 if-else语句
  • 特点:带优先级的选择结构。

  • 示例:

    always @(sel or a or b) begin
      if (sel == 1'b1)
        y = a;    // sel为1选a
      else 
        y = b;    // 否则选b
    end
    
    1
    2
    3
    4
    5
    6
# 4.2 case语句
  • 特点:多路分支,无优先级。

  • 特殊形式:

    • casez:忽略z(高阻)和?(无关位)
    • casex:忽略x(未知)、z和?
  • 示例(BCD译码器):

    case(num)
      4'd0: seg = 7'b1111110;  // 显示数字0
      4'd1: seg = 7'b0110000;  // 显示数字1
      default: seg = 7'bx;     // 其他情况输出未知
    endcase
    
    1
    2
    3
    4
    5

# 5. 循环语句:硬件也能"循环"?

# 5.1 for循环 - 可综合的循环
  • 特点:编译时会展开为硬件结构。

  • 示例(位反转):

    for(i=0; i<8; i=i+1)
      rev[7-i] = data[i];  // 生成8个并行的连线
    
    1
    2
# 5.2 其他循环(仿真用)
  • forever:无限循环(如生成时钟)

    initial forever #10 clk = ~clk;  // 每10ns翻转
    
    1
  • repeat:固定次数循环

    repeat(5) @(posedge clk);  // 等待5个时钟周期
    
    1

# 6. 关键注意事项

  1. reg不一定生成寄存器:

    • 在always块中用=赋值可能生成组合逻辑
    • 只有时钟触发的<=才会生成触发器
  2. 敏感列表要完整:

    // 组合逻辑必须列出所有输入!
    always @(a or b or sel) // 漏掉sel会导致bug
    
    1
    2
  3. 避免锁存器:

    • if缺少else分支
    • case缺少default
    • 解决办法:确保所有路径都有赋值

# 三、 结构化建模是啥?

核心思想:像搭积木一样用现成的模块/门电路来构建系统,直接对应硬件层次结构,说白了就是面向对象设计。

类比:

  • 模块级:用现成的CPU、内存等大组件拼电脑
  • 门级:用与门、或门等小零件搭电路
  • 开关级:用晶体管构建最基础的逻辑门

# 2. 模块级建模:调用现成模块

# 2.1 基本调用方式
// 定义子模块(积木)
module AND_gate(input a, b, output y);
  assign y = a & b;
endmodule

// 顶层模块(拼积木)
module TOP(input x1, x2, output z);
  wire w;
  // 实例化子模块(两种方式)
  AND_gate U1(x1, x2, w);  // 方式1:按顺序连接
  AND_gate U2(.a(w), .b(x1), .y(z)); // 方式2:按名称连接(推荐!)
endmodule
1
2
3
4
5
6
7
8
9
10
11
12
# 2.2 参数化模块
module #(parameter WIDTH=4) 
  Adder(input [WIDTH-1:0] a,b, output [WIDTH:0] sum);
  assign sum = a + b;
endmodule

// 调用时修改参数
Adder #(8) U3(a_8bit, b_8bit, sum_8bit); // 8位加法器
1
2
3
4
5
6
7

# 3. 门级建模:调用基本逻辑门

# 3.1 Verilog内置门类型
门类型 关键字 示例
与门 and and U1(out, a, b);
或门 or or U2(out, a, b, c);
非门 not not U3(out, in);
三态缓冲器 bufif1 bufif1 U4(out, in, ctrl);
# 3.2 实际案例:2-4译码器
module decoder(
  input [1:0] sel,
  input en,
  output [3:0] y
);
  wire not_sel0, not_sel1;
  
  // 基本门调用
  not U1(not_sel0, sel[0]);
  not U2(not_sel1, sel[1]);
  
  nand U3(y[0], en, not_sel1, not_sel0);
  nand U4(y[1], en, not_sel1, sel[0]);
  nand U5(y[2], en, sel[1], not_sel0);
  nand U6(y[3], en, sel[1], sel[0]);
endmodule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 4. 开关级建模:晶体管级描述

# 4.1 MOS开关类型
类型 关键字 功能
NMOS nmos 控制=1时导通
PMOS pmos 控制=0时导通
CMOS cmos 双控制(nctrl和pctrl互补)
双向开关 tran 两端直接连通
# 4.2 CMOS与非门实现
module NAND(
  input a, b,
  output y
);
  supply1 VDD;  // 电源
  supply0 GND;  // 地
  
  pmos P1(y, VDD, a);
  pmos P2(y, VDD, b);
  nmos N1(y, mid, a);
  nmos N2(mid, GND, b);
endmodule
1
2
3
4
5
6
7
8
9
10
11
12

# 5. 关键注意事项

  1. 端口连接陷阱:

    // 危险!容易接反
    Sub_module U1(a, b);  
    // 安全推荐
    Sub_module U1(.port_a(a), .port_b(b));
    
    1
    2
    3
    4
  2. 参数传递优先级:

    • #(参数)直接传递 > defparam语句
  3. 开关级设计限制:

    • 通常只用于ASIC设计
    • FPGA综合经常忽略开关级细节

# 总结

  • 核心价值:
    • 模块化设计:提高代码复用性
    • 贴近物理实现:适合性能优化
    • 混合使用:高层用行为级,底层用结构化
  • 典型应用:
    • 数字IP核集成(如调用现成的存储器、PLL)
    • 标准单元库开发
    • 晶体管级电路设计

# ** 三种建模方式对比**

特性 结构化建模 行为级建模 数据流建模
抽象级别 中等(门/模块级) 高(算法级) 中(信号流级)
主要语句 模块/门实例化 always/initial assign
可读性 直观但繁琐 最易读 中等
应用场景 IP模块集成、标准单元设计 复杂逻辑/状态机 简单组合逻辑
硬件对应 直接映射 依赖综合工具 直接映射
帮助我们改善此页面 (opens new window)
上次更新: 2025/07/12, 16:01:22
01.VerilogHDL的坤本素养

← 01.VerilogHDL的坤本素养

Theme by Vdoing | Copyright © 2025-2025 Eryajf | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式