VHDL/Verilog 硬件描述语言:组合与时序逻辑设计
FreeGuideOnline
最新
2026-06-15
VHDL/Verilog 硬件描述:组合与时序逻辑设计
硬件描述语言(HDL)是数字电路设计的基础,VHDL 和 Verilog 是两大主导标准。本教程聚焦于如何使用这两种语言实现组合逻辑与时序逻辑,从基本概念到可综合代码范例,帮助初学者快速上手。
1. 硬件描述语言的核心概念
在开始之前,理解 HDL 与软件编程语言的本质区别:
- 描述硬件而非算法:代码对应逻辑门、触发器等物理结构,执行是并行的。
- 可综合与不可综合:只有符合特定编码风格的代码才能被 EDA 工具转化为门级网表,本教程仅限可综合设计。
- 两种主流语言:Verilog 语法类似 C,简洁灵活;VHDL 语法严格,强类型,适合大型项目。二者在组合和时序逻辑设计上遵循相同的硬件思想。
2. 组合逻辑设计
2.1 组合逻辑概念
组合逻辑的输出仅取决于当前输入,无记忆元件。典型电路:译码器、多路选择器、加法器。设计要点:避免生成锁存器,确保所有输入情况都有输出赋值。
2.2 Verilog 中的组合逻辑
Verilog 使用 assign 连续赋值语句或 always @(*) 块描述组合逻辑。
连续赋值(assign)
// 2 输入多路选择器
module mux2_1 (
input a, b, sel,
output y
);
assign y = sel ? b : a;
endmodule
阻塞赋值(=)的 always 块
// 三态缓冲器
module tri_buf (
input en, data_in,
output reg data_out
);
always @(*) begin
if (en)
data_out = data_in;
else
data_out = 1'bz; // 高阻态
end
endmodule
关键规则:
- 敏感信号列表用
@(*)自动包含所有输入,避免遗漏。 - 使用阻塞赋值
=。 - 不要部分赋值,务必在条件分支结束前为所有输出赋值,否则综合出锁存器。
2.3 VHDL 中的组合逻辑
VHDL 组合逻辑通常用并发的信号赋值或 process 语句实现。
并发信号赋值
-- 4 位加法器
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port (
a, b : in std_logic_vector(3 downto 0);
sum : out std_logic_vector(4 downto 0)
);
end adder;
architecture comb of adder is
begin
sum <= std_logic_vector(unsigned('0' & a) + unsigned('0' & b));
end comb;
含 process 的组合逻辑
-- 优先编码器
process(a) begin
if a(3) = '1' then y <= "100";
elsif a(2) = '1' then y <= "011";
elsif a(1) = '1' then y <= "010";
elsif a(0) = '1' then y <= "001";
else y <= "000";
end if;
end process;
VHDL 规则:
- 敏感信号列表必须包含所有被读取的信号(或使用
all)。 - 使用信号赋值
<=,但 process 内部仍然为顺序执行。 - 同样需避免锁存器:务必在条件分支最后覆盖所有情况。
3. 时序逻辑设计
3.1 时序逻辑概念
时序逻辑的输出不仅取决于当前输入,还取决于先前状态,依赖时钟边沿触发。常见元件:触发器(FF)、寄存器、计数器。设计核心:时钟信号与复位策略。
3.2 Verilog 中的时序逻辑
使用 always @(posedge clk) (或 negedge)描述边沿触发行为,并要求使用非阻塞赋值 <=。
带异步复位的 D 触发器
module dff (
input clk, rst_n, d,
output reg q
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
q <= 1'b0; // 异步低有效复位
else
q <= d;
end
endmodule
同步使能的寄存器
module reg_en (
input clk, en, d,
output reg q
);
always @(posedge clk) begin
if (en)
q <= d;
end
endmodule
规则:
- 时序 always 块必须只有时钟边沿和异步复位/置位出现在敏感列表里,不可混合其他信号。
- 使用非阻塞赋值
<=,避免竞争冒险。 - 不要在同一个 always 块中混合组合逻辑。
3.3 VHDL 中的时序逻辑
VHDL 使用 process(clk, async_reset) 来描述触发器。
带异步复位的 D 触发器
process(clk, rst_n) begin
if rst_n = '0' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
同步复位计数器
process(clk) begin
if rising_edge(clk) then
if rst = '1' then
cnt <= (others => '0');
else
cnt <= cnt + 1;
end if;
end if;
end process;
VHDL 规则:
- 敏感列表里时钟和异步控制信号必须一起列出。
- 复位条件判断必须在时钟边沿检测之前(若异步)。
- 信号赋值仍然使用
<=。
4. 混合设计实例:有限状态机(FSM)
FSM 是经典的组合与时序逻辑混合结构。将时序部分(状态寄存器)与组合部分(次态逻辑、输出逻辑)分离。
Verilog:三段式状态机
module fsm (
input clk, rst_n, in,
output reg out
);
reg [1:0] state, next_state;
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10;
// 时序逻辑:状态更新
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
state <= S0;
else
state <= next_state;
end
// 组合逻辑:次态计算
always @(*) begin
case (state)
S0: next_state = in ? S1 : S0;
S1: next_state = in ? S2 : S0;
S2: next_state = in ? S2 : S0;
default: next_state = S0;
endcase
end
// 组合逻辑:输出(此处为 Moore 型)
always @(*) begin
case (state)
S0: out = 0;
S1: out = 0;
S2: out = 1;
default: out = 0;
endcase
end
endmodule
VHDL:两段式状态机
architecture rtl of fsm is
type state_type is (S0, S1, S2);
signal state, next_state : state_type;
begin
-- 时序部分
process(clk, rst_n) begin
if rst_n = '0' then
state <= S0;
elsif rising_edge(clk) then
state <= next_state;
end if;
end process;
-- 组合部分
process(state, in) begin
case state is
when S0 =>
next_state <= S1 when in = '1' else S0;
out <= '0';
when S1 =>
next_state <= S2 when in = '1' else S0;
out <= '0';
when S2 =>
next_state <= S2 when in = '1' else S0;
out <= '1';
end case;
end process;
end rtl;
5. 设计要点与常见陷阱
- 避免锁存器:组合逻辑中 if/case 未覆盖所有分支,且输出未赋默认值时,综合工具会推断出锁存器(latch),在同步设计中通常非期望。解决方法:使用
else或default覆盖全部分支。 - 区分阻塞/非阻塞赋值 (Verilog):组合逻辑用
=,时序逻辑用<=。混用会导致仿真与综合不一致。 - 时钟域处理:本教程仅限单时钟域设计,跨时钟域需额外同步电路(双触发器、FIFO等)。
- 初始化与复位:FPGA 设计中寄存器可依靠初始块或复位。强烈建议采用复位信号,确保上电状态确定。
- 可综合性检查:不要在可综合代码中使用
initial、fork、#delay等仿真语句;VHDL 中避免wait等不可综合结构。
6. 总结
- 组合逻辑:纯函数,输出仅取决于当前输入,Verilog 用
assign/always @(*), VHDL 用并发或含所有输入的process。 - 时序逻辑:依赖时钟边沿,用
always @(posedge clk)(Verilog) 或process(clk)(VHDL),必须使用非阻塞赋值(Verilog)。 - FSM 是组合与时序结合的典型模板,三段式 (Verilog) 或两段式 (VHDL) 编码风格清晰、易维护。
- 严格遵守各语言的编码规范,可以轻松写出正确、高效、可移植的硬件设计。
通过掌握这些基本构件,你已经能够构建绝大多数数字电路。建议在实际项目的仿真和综合中反复练习,将理论知识内化为工程直觉。