3、硬件描述语言基础:Verilog与VHDL对比、模块化设计思想、并行与顺序语句的理解

好,咱们今天聊聊硬件描述语言。很多刚入行的朋友问我,Verilog和VHDL到底选哪个?我的回答是——别纠结,两个都得会看,但入门我推荐Verilog。

为什么?说白了,Verilog的语法更像C,上手快。我当年在学校里先学的VHDL,那叫一个痛苦。后来工作中接触Verilog,三天就能写模块了。但这不是说VHDL不好,它严谨,适合大型项目。

3.1 Verilog与VHDL:一场没有输家的对比

先看个直观的对比表:

对比项 Verilog VHDL
语法风格 类C,简洁 类Ada,严谨
数据类型 reg、wire,相对简单 std_logic、integer等,类型丰富
设计粒度 适合RTL级描述 适合系统级描述
学习曲线 平缓,易上手 陡峭,但逻辑清晰
行业应用 ASIC/FPGA主流 军工、航天领域常见

我个人习惯是:写模块用Verilog,看文档用VHDL。你想想看,一个项目组里,可能两种语言混着用。我遇到过最夸张的一次,一个IP核用Verilog写,测试bench用VHDL写,仿真照样跑得飞起。

核心观点:语言只是工具,思想才是灵魂。不管用哪种语言,你描述的都是硬件电路,不是软件程序。

3.2 模块化设计思想:把大问题拆成小积木

模块化设计,说白了就是“分而治之”。一个复杂的FPGA设计,如果全写在一个文件里,那调试起来简直是噩梦。

我一般这样划分模块:

  • 顶层模块:只做连线,不写逻辑。就像PCB上的插座,只管把各个子模块插上去。
  • 功能模块:每个模块只做一件事。比如一个UART模块,只负责串口收发。
  • 接口清晰:模块之间的信号越少越好。我见过有人一个模块引出50个端口,那还不如不拆。

举个例子,一个简单的计数器模块:

// Verilog 计数器模块
module counter (
    input  wire       clk,
    input  wire       rst_n,
    input  wire       en,
    output reg  [7:0] count
);
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            count <= 8'd0;
        else if (en)
            count <= count + 1'b1;
    end
endmodule

你看,这个模块只做计数。如果哪天要改成减法计数,我只需要改这一处,其他模块完全不受影响。这就是模块化的好处。

小技巧:写模块时,先画接口图,再写代码。我习惯用Excel列个端口清单,标清楚方向、位宽、功能。这样写代码时思路特别清晰。

3.3 并行与顺序语句:硬件思维的分水岭

这是很多新手栽跟头的地方。软件里,代码是一行一行执行的。硬件里呢?所有模块同时跑!

我举个例子你就明白了。假设有两个always块:

// 并行执行的两个always块
always @(posedge clk) begin
    a <= b;
end

always @(posedge clk) begin
    b <= a;
end

在软件里,这会产生死循环。但在硬件里,每个时钟沿,a和b同时交换值。为什么会这样?因为这两个always块对应的是两个独立的寄存器,它们并行工作。

再来看顺序语句。always块内部的begin...end,是顺序执行的。但要注意,这里的“顺序”只在一个时钟周期内有效:

always @(posedge clk) begin
    temp = a + b;   // 先计算
    c = temp + d;   // 再用结果
end

这里用的是阻塞赋值“=”,所以顺序执行。如果换成非阻塞赋值“<=”,结果就完全不同了。

避坑指南:我曾经在一个项目中,把组合逻辑里的阻塞赋值和非阻塞赋值混用了。结果仿真没问题,上板子就乱跳。查了两天才发现,是赋值方式用错了。记住:时序逻辑用非阻塞“<=”,组合逻辑用阻塞“=”。

为了帮你理清思路,我画了张图:

硬件描述语言核心知识体系 语言对比 Verilog:类C,简洁 VHDL:类Ada,严谨 共同点:描述硬件 选择建议: 入门用Verilog 大型项目用VHDL 实际工作中混用 模块化设计 顶层模块:只连线 功能模块:单一职责 接口清晰:少端口 设计原则: 高内聚,低耦合 先画接口图 再写代码 并行与顺序 并行:always块之间 顺序:begin...end内 阻塞赋值(=):顺序 非阻塞赋值(<=):并行 使用规则: 时序逻辑用<= 组合逻辑用= 核心:用硬件思维写代码,而不是软件思维

这张图把三个核心知识点串起来了。你仔细看,左边是语言选择,中间是设计方法,右边是执行机制。三者缺一不可。

最后说一句心里话:学硬件描述语言,别死记语法。多想想“这个代码综合出来是什么电路”。我见过太多人,写出来的代码仿真没问题,综合出来一堆锁存器。嗯,这就是没理解并行和顺序的区别。

好了,这一章就到这里。记住:Verilog和VHDL只是工具,模块化是方法,并行思维是核心。把这三点吃透了,后面的路就好走了。

本章要点回顾:

  • Verilog适合快速开发,VHDL适合严谨项目
  • 模块化设计要遵循“单一职责”原则
  • 并行是硬件的本质,顺序是局部的行为
  • 阻塞赋值和非阻塞赋值不能混用

专注资料整理