第一章:RTL设计基础
各位同学,咱们今天聊聊RTL设计的根基。说实话,我见过太多新手一上来就急着写代码,结果后面调试到崩溃。RTL设计就像盖房子,地基不牢,后面全是坑。
1.1 数字电路回顾
先快速过一下数字电路的核心概念。你想想看,数字电路说白了就是0和1的游戏。但别小看这两个数字,它们背后是实实在在的电压信号。
核心要点:数字电路只有两种状态——高电平(1)和低电平(0)。但实际芯片里,电压会有波动,所以有噪声容限的概念。
我记得刚入行时,有个老工程师跟我说:「数字电路是模拟电路的抽象」。当时不理解,后来做高速设计时才发现,信号上升沿太慢、毛刺太多,数字逻辑根本没法正常工作。嗯,这里要注意,理想和现实是有差距的。
1.2 Verilog/VHDL语法速览
我个人习惯用Verilog,但VHDL也有它的优势。咱们快速过一下最常用的语法结构。
Verilog 模块结构
module counter (
input wire clk,
input wire rst_n,
output reg [3:0] count
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
count <= 4'd0;
else
count <= count + 1'b1;
end
endmodule
这段代码,说白了就是一个4位计数器。注意看always块里的敏感列表——我建议新手一定要搞清楚组合逻辑和时序逻辑的区别。组合逻辑用@(*),时序逻辑用@(posedge clk)。
小技巧:写Verilog时,我习惯把复位信号命名为rst_n,下划线n表示低电平有效。这样一看就知道是异步复位,不用猜。
VHDL 快速对比
entity counter is
port (
clk : in std_logic;
rst_n : in std_logic;
count : out std_logic_vector(3 downto 0)
);
end entity;
architecture rtl of counter is
signal cnt_reg : unsigned(3 downto 0);
begin
process(clk, rst_n)
begin
if rst_n = '0' then
cnt_reg <= (others => '0');
elsif rising_edge(clk) then
cnt_reg <= cnt_reg + 1;
end if;
end process;
count <= std_logic_vector(cnt_reg);
end architecture;
VHDL的语法更严谨,但写起来也啰嗦。我个人觉得,做项目用哪种语言不重要,重要的是设计思路要清晰。
1.3 组合逻辑与时序逻辑
这是新手最容易搞混的地方。我直接说结论:
- 组合逻辑:输出只取决于当前输入,没有记忆功能。比如与门、或门、加法器。
- 时序逻辑:输出不仅取决于当前输入,还取决于之前的状态。比如触发器、计数器、状态机。
避坑指南:我曾经犯过一个低级错误——在组合逻辑里用了always @(posedge clk),结果综合出来一堆锁存器。后来查了半天才发现,组合逻辑应该用always @(*),而且赋值要用阻塞赋值=,时序逻辑才用非阻塞赋值<=。
为什么会这样?因为组合逻辑没有时钟,它只是根据输入实时计算输出。而时序逻辑需要时钟沿来采样数据,所以必须用非阻塞赋值来避免竞争冒险。
1.4 同步设计原则
同步设计,说白了就是所有时序逻辑都在同一个时钟沿下工作。这是FPGA设计的黄金法则。
| 原则 | 说明 | 我的经验 |
|---|---|---|
| 单时钟域 | 尽量使用单一全局时钟 | 多时钟域处理不好,时序收敛就是噩梦 |
| 避免异步复位 | 尽量使用同步复位或异步复位同步释放 | 我见过异步复位导致亚稳态的案例 |
| 寄存器输出 | 所有输出都经过寄存器打一拍 | 这是时序收敛的捷径 |
| 避免组合反馈 | 组合逻辑的输出不能直接反馈到输入 | 否则会形成锁存器,综合工具会报warning |
你想想看,如果设计里用了两个不同频率的时钟,数据跨时钟域传输时,很容易出现亚稳态。我建议新手先老老实实做单时钟域设计,等熟练了再碰多时钟域。
核心原则:同步设计 = 所有触发器都在同一个时钟沿采样 + 组合逻辑夹在触发器之间。
知识体系总览
下面这张图,是我自己总结的RTL设计知识体系。你看一眼,心里就有谱了。
这张图把咱们这章的核心内容串起来了。你仔细看看,数字电路是基础,语法是工具,组合/时序逻辑是核心概念,同步设计是实践准则。四者缺一不可。
我的建议:刚开始学RTL设计,别急着写复杂代码。先把同步设计原则刻在脑子里,然后从简单的计数器、状态机开始练手。我当年就是靠一个8位计数器入门FPGA的,现在想想,基础打牢了,后面学什么都快。
好了,这一章的内容就到这里。记住,RTL设计不是写软件,而是画电路。你写的每一行代码,最终都会变成实实在在的硬件。所以,下笔之前,先想清楚电路长什么样。