• 正文
  • 相关推荐
申请入驻 产业图谱

Verilog入门指南:从软件思维到硬件描述

11/27 09:58
776
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

当你第一次接触Verilog时,很容易把它当成C或Java这样的编程语言。这是一个常见的误区,也是入门路上的第一个坎。Verilog不是一种编程语言,而是一种硬件描述语言 你的角色不是“写程序”,而是在“画图纸”——用代码的形式描述一个数字电路应该长什么样。

一、核心思想:你是在描述电路

在开始写代码之前,请务必建立这个思维模型:

软件程序:是指令的序列,在CPU按时间顺序执行。

硬件描述:定义的是电路的结构和行为,所有逻辑门寄存器同时(并行) 工作。

理解了这一点,你就能明白为什么Verilog代码的执行方式如此不同。

二、第一个Verilog模块:一盏可控的灯

让我们从一个最简单的例子开始:描述一个能被开关控制的灯。

在数字电路中,这就是一个与门Light = Switch & Power

我们用Verilog这样描述它:

// 定义一个名为 "light_switch" 的模块
module light_switch (
    input wire power,    // 输入端口:点点怎么样
线
    input wire switch,   // 输入端口:开关线
    output wire light    // 输出端口:灯线
);
    // 核心逻辑:灯亮 <= 当电源接通 "并且" 开关打开
    assign light = power & switch;

endmodule

让我们拆解这个模块的构成:

module ... endmodule:定义一个电路模块的边界,就像定义一个函数或一个类。

input wire / output wire:定义模块的输入和输出端口,也就是这个点点taptap安卓的“引脚”。

assign:这是一个“连续赋值”语句。它意味着右侧信号(power & switch)的任何变化,都会立即反映到左侧信号(light)上。这直接描述了一个组合逻辑电路

三、描述电路的两种基本方式:组合逻辑 vs 时序逻辑

数字电路的两大基石,在Verilog中也有对应的描述风格。

1. 组合逻辑:输出只取决于当前的输入就像我们的“可控灯”,没有记忆功能。除了用 assign,更复杂的情况常用 always @(*) 块。

// 一个2选1选择器 (MUX)
module mux2to1 (
    inputwire a,
    inputwire b,
    inputwire sel, // 选择信号
    outputreg out  // 输出定义为寄存器类型
);

    // always块:当a, b, sel中任何一个变化时,执行内部的代码
    always @(*) begin
        if (sel == 1'b0) begin
            out = a;
        end
        elsebegin
            out = b;
        end
    end

endmodule

关键点:在组合逻辑的 always 块中,我们使用 **阻塞赋值 (=)**,就像在C语言中一样,语句是按顺序立即计算的。

2. 时序逻辑:输出取决于当前输入和过去的状态

有时钟,有记忆功能,最典型的就是触发器 (Flip-Flop)。

// 一个最简单的D触发器
module d_flip_flop (
    inputwire clk,    // 时钟信号
    inputwire rst_n,  // 复位信号 (低电平有效)
    inputwire d,      // 数据输入
    outputreg q       // 数据输出
);

    // always块:只在时钟的上升沿触发
    always @(posedge clk ornegedge rst_n) begin
        if (!rst_n) begin// 如果复位信号为低
            q <= 1'b0;    // 输出q被强制清零
        end
        elsebegin        // 否则,在时钟上升沿
            q <= d;       // 将输入d的值锁存到输出q
        end
    end

endmodule

关键点

always @(posedge clk ...):表示这个块只在时钟上升沿复位下降沿触发。

非阻塞赋值 (<=):这是时序逻辑的标志。它意味着所有 <= 赋值在计算完右侧表达式后,同时在时间步结束时更新。这精确模拟了寄存器在时钟边沿同时动作的硬件行为。

黄金法则

描述组合逻辑:用 always @(*) 和 **阻塞赋值 (=)**。

描述时序逻辑:用 always @(posedge clk) 和 **非阻塞赋值 (<=)**。

严禁在同一个 always 块中混合使用 = 和 <=

四、入门第一步:从一个简单的项目开始

理论学习之后,最好的方式是实践。

安装EDA工具:推荐 Intel Quartus Prime (免费版) 或 Xilinx Vivado (免费版)。它们是行业标准,可以进行设计、仿真和综合。

编写你的第一个模块:尝试实现一个4位计数器

进行仿真:编写一个简单的Testbench(测试平台),给你的模块输入激励(比如时钟和复位信号),观察输出波形,看它是否符合预期。这是验证硬件设计正确性的唯一途径。

五、常用资源与下一步

HDLBits:一个在线的Verilog练习平台,像LeetCode for Verilog,非常适合初学者循序渐进地学习。

《Verilog数字系统设计教程》:经典的入门教材。

下一步:当你掌握了基础,可以继续学习:Testbench编写、状态机设计、FIFO、时钟域交叉等高级主题。


总结

入门Verilog,本质上是完成一次思维模式的转换——从串行的软件思维,切换到并行的硬件思维。请记住,你写的每一行代码,背后都对应着真实的逻辑门、连线和寄存器。

从描述一个简单的与门开始,到实现一个复杂的处理器,其核心思想始终如一:你是在用代码,构建一个数字世界。 祝你学习顺利!

相关推荐

Baidu
map