当前位置: 首页 > news >正文

嵌入式系统 VHDL 入门笔记:从语法到状态机

一、VHDL 是什么?底层原理与语言基础

1.1 VHDL 的定位

VHDL(VHSIC Hardware Description Language)是一种硬件描述语言(HDL),用于描述数字电路的结构与行为。它不是传统意义上的编程语言——你写的 VHDL 最终会被综合工具(Synthesis Tool)映射为 FPGA/CPLD 中的逻辑门、触发器、连线,或在仿真器中按事件驱动方式执行。

可以把它理解为:

层次含义
行为级IF/CASE/PROCESS描述"做什么"
RTL 级综合后形成寄存器 + 组合逻辑(最常用)
门级/结构级实例化具体元件,如AND2DFF

1.2 与 Verilog 的简要对比

特性VHDLVerilog
语法风格强类型、Ada 风格C 风格,较宽松
类型系统严格(STD_LOGICvsBIT较灵活
可读性大型工程结构清晰代码更紧凑
工业应用欧洲航天/军工较多北美 ASIC/FPGA 较多

两者都能描述同样的硬件,选哪种通常取决于团队习惯与工具链。

1.3 底层执行模型:事件驱动仿真

VHDL 仿真器采用事件驱动模型:

  1. 信号(Signal)赋值<=调度的,在当前PROCESS结束前不会更新,所有进程执行完毕后统一生效(delta cycle)。
  2. 变量(Variable)赋值:=立即生效的,仅在当前进程内可见。
  3. 敏感列表决定组合逻辑进程何时重新执行;时序进程通常只对时钟边沿敏感。

笔记中 JK 触发器的修正(q <= q1放在PROCESS外)正是信号延迟更新特性的体现——下文会详细说明。

1.4 标准库与数据类型

-- 几乎所有设计都需要的库声明(复制即可) LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; -- STD_LOGIC、逻辑运算 USE IEEE.STD_LOGIC_ARITH.ALL; -- 算术运算(较老,部分工具仍支持) USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- 无符号向量加减

常用类型:

类型含义示例
STD_LOGIC单 bit,九态逻辑'0','1','Z','U'
STD_LOGIC_VECTOR(n DOWNTO 0)bit 向量"1010"
INTEGER仿真用整数VARIABLE sum : INTEGER

引号规则

  • 单 bit单引号'0','1'
  • 多位向量双引号"00","1111"

1.5 VHDL 文件三段式结构

每个.vhd文件通常包含三层,自顶向下:

┌─────────────────────────┐ │ Library & Package │ 库与包引用 ├─────────────────────────┤ │ Entity(实体) │ 对外接口:端口名、方向、类型 ├─────────────────────────┤ │ Architecture(结构体) │ 内部实现:行为/结构/数据流 └─────────────────────────┘

命名约定ENTITY名与文件名一致,且ENTITY ... ISEND ENTITY ...首尾呼应。


二、基本结构示例:逻辑门

2.1 实体模板

-- Library and package LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- entity:定义模块对外接口 ENTITY e_name IS PORT( in1, in2, in3 : IN STD_LOGIC; -- 输入端口 out1, out2 : OUT STD_LOGIC -- 输出端口 ); END ENTITY e_name; -- architecture:定义模块内部行为 ARCHITECTURE arch_name OF e_name IS BEGIN -- 具体逻辑写在这里 END ARCHITECTURE arch_name;

说明:库声明部分日常写代码时直接复制即可,无需每次手敲。

2.2 逻辑门测试模块logic_test

-- entity ENTITY logic_test IS PORT( a, b, c, d : IN STD_LOGIC; and_OUT, or_OUT : OUT STD_LOGIC ); END ENTITY logic_test; -- architecture ARCHITECTURE bhv OF logic_test IS BEGIN and_OUT <= a AND b; -- 2 输入与门 or_OUT <= a OR b OR c OR d; -- 4 输入或门 END ARCHITECTURE bhv;

要点<=用于信号赋值;ANDORNOT等是STD_LOGIC_1164包中的重载运算符,可直接用于单 bit 运算。


三、组合逻辑

3.1 二选一多路选择器(2-to-1 MUX)

电路原理

选择信号S(笔记中记为ch)决定输出取自A还是B

Output = (A · S̄) + (B · S)

即:S=0 选 A,S=1 选 B。

电路说明:顶部输入为选择端 S,经反相器后分别与 A、B 做与运算,再经或门输出。这是 MUX 的经典门级实现,与下方行为描述等价。

电路原理图:

VHDL 实现mux2
-- Library and package LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- entity ENTITY mux2 IS PORT( a, b, ch : IN STD_LOGIC; -- a/b 为数据输入,ch 为选择端 data : OUT STD_LOGIC -- 输出 ); END ENTITY mux2; -- architecture:行为级描述 ARCHITECTURE bhv OF mux2 IS BEGIN PROCESS(a, b, ch) -- 敏感列表:任一输入变化即重新计算 BEGIN IF ch = '0' THEN data <= a; -- 选择 A ELSE data <= b; -- 选择 B END IF; END PROCESS; END ARCHITECTURE bhv;

3.2 四选一多路选择器(4-to-1 MUX)

写法一:嵌套 IF(独立选择位 ch0、ch1)
-- Library and package LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- entity ENTITY mux4 IS PORT( a, b, c, d : IN STD_LOGIC; ch0, ch1 : IN STD_LOGIC; -- 两位选择信号 data : OUT STD_LOGIC ); END ENTITY mux4; -- architecture ARCHITECTURE bhv OF mux4 IS BEGIN PROCESS(a, b, c, d, ch0, ch1) BEGIN IF ch1 = '0' THEN IF ch0 = '0' THEN data <= a; -- ch1ch0 = 00 ELSE data <= b; -- ch1ch0 = 01 END IF; ELSE IF ch0 = '0' THEN data <= c; -- ch1ch0 = 10 ELSE data <= d; -- ch1ch0 = 11 END IF; END IF; END PROCESS; END ARCHITECTURE bhv;
写法二:CASE 语句(推荐,更简洁)
-- entity(使用 2 位向量作为选择端) ENTITY mux4 IS PORT( a, b, c, d : IN STD_LOGIC; ch : IN STD_LOGIC_VECTOR(1 DOWNTO 0); data : OUT STD_LOGIC ); END ENTITY mux4; -- architecture ARCHITECTURE bhv OF mux4 IS BEGIN PROCESS(a, b, c, d, ch) BEGIN CASE ch IS WHEN "00" => data <= a; WHEN "01" => data <= b; WHEN "10" => data <= c; WHEN "11" => data <= d; WHEN OTHERS => data <= '0'; -- 兜底,防止 latch END CASE; END PROCESS; END ARCHITECTURE bhv;

语法提醒:多位二进制用双引号"00",单位 bit 用单引号'0'


3.3 数码管编码器seg7

将 4 bit BCD 码(0~9)转换为 8 bit 段码,驱动共阳极/共阴极七段数码管。

-- Library and package LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- entity ENTITY seg7 IS PORT( en : IN STD_LOGIC; -- 使能:'1' 时关闭显示 dat : IN STD_LOGIC_VECTOR(3 DOWNTO 0); -- 4 bit 输入数据 display : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) -- 8 bit 段码输出 (a~g + dp) ); END ENTITY seg7; -- architecture ARCHITECTURE bhv OF seg7 IS BEGIN PROCESS(en, dat) BEGIN IF en = '1' THEN display <= "11111111"; -- 使能无效,全部熄灭 ELSE CASE dat IS WHEN "0000" => display <= "11111100"; -- 数字 0 WHEN "0001" => display <= "01100000"; -- 数字 1 WHEN "0010" => display <= "11011010"; -- 数字 2 WHEN "0011" => display <= "11110010"; -- 数字 3 WHEN "0100" => display <= "01100110"; -- 数字 4 WHEN "0101" => display <= "10110110"; -- 数字 5 WHEN "0110" => display <= "10111110"; -- 数字 6 WHEN "0111" => display <= "11100100"; -- 数字 7 WHEN "1000" => display <= "11111110"; -- 数字 8 WHEN "1001" => display <= "11110110"; -- 数字 9 WHEN OTHERS => display <= "00000000"; -- 非法输入 END CASE; END IF; END PROCESS; END ARCHITECTURE bhv;

图说明:右侧 10 个七段管示意图标注了 a~g 各段与 dp(小数点)的对应关系,绿色高亮段即为该数字需要点亮的部分,与CASE中的 8 bit 编码一一对应。

图说明seg7模块左侧接入使能en与 4 bit 数据dat,右侧 8 路输出分别驱动数码管各段。


3.4 多人表决器vote13

13 人投票,超过半数(≥7 票)则输出'1'

-- entity ENTITY vote13 IS PORT( vt : IN STD_LOGIC_VECTOR(13 DOWNTO 1); -- 13 路投票输入 result : OUT STD_LOGIC -- 表决结果 ); END ENTITY vote13; -- architecture ARCHITECTURE bhv OF vote13 IS BEGIN PROCESS(vt) VARIABLE sum : INTEGER RANGE 0 TO 13; -- 变量:进程内立即更新 BEGIN sum := 0; FOR i IN 1 TO 13 LOOP IF vt(i) = '1' THEN sum := sum + 1; -- 统计赞成票 END IF; END LOOP; IF sum >= 7 THEN result <= '1'; -- 超过半数 ELSE result <= '0'; END IF; END PROCESS; END ARCHITECTURE bhv;

图说明:13 路输入(A~M)各自进入逻辑门阵列,最终汇聚为单 bit 输出。行为上等价于"统计 1 的个数并与阈值 7 比较",属于纯组合逻辑。


四、时序逻辑:触发器

4.1 D 触发器

基础版(无复位)
-- Library and package LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- entity ENTITY dff IS PORT( clk, d : IN STD_LOGIC; q : OUT STD_LOGIC ); END ENTITY dff; -- architecture ARCHITECTURE bhv OF dff IS BEGIN PROCESS(clk) BEGIN -- 下降沿触发:检测 clk 事件且当前值为 '0' IF (clk'EVENT AND clk = '0') THEN q <= d; END IF; END PROCESS; END ARCHITECTURE bhv;

工业设计中更常见上升沿clk='1'),原理相同,改一处即可。

同步清零 / 置位版

清零(clr)和置位(set)在时钟边沿内判断,属于同步控制;时钟优先级最高。

-- entity ENTITY dff IS PORT( clk, d, clr, set : IN STD_LOGIC; q : OUT STD_LOGIC ); END ENTITY dff; -- architecture ARCHITECTURE bhv OF dff IS BEGIN PROCESS(clk) BEGIN IF (clk'EVENT AND clk = '0') THEN IF clr = '1' THEN q <= '0'; -- 同步清零,优先级高于 set ELSIF set = '1' THEN q <= '1'; -- 同步置位 ELSE q <= d; -- 正常采样 END IF; END IF; END PROCESS; END ARCHITECTURE bhv;
异步清零 / 置位版

clrset放入敏感列表,且在时钟判断之前执行——不等待时钟,立即生效。

-- architecture ARCHITECTURE bhv OF dff IS BEGIN PROCESS(clk, clr, set) -- 异步控制必须加入敏感列表 BEGIN IF clr = '1' THEN q <= '0'; -- 异步清零 ELSIF set = '1' THEN q <= '1'; -- 异步置位 ELSIF (clk'EVENT AND clk = '0') THEN q <= d; -- 下降沿采样 END IF; END PROCESS; END ARCHITECTURE bhv;
类型敏感列表生效时机
同步复位clk时钟边沿
异步复位clk, rst, ...立即,优先级高于时钟

4.2 JK 触发器

功能说明

图说明

  • clrset低电平有效的异步控制端(符号上的小圆圈表示取反)
  • 时钟上升沿时:
    • J=0, K=1 → Q 清零
    • J=1, K=0 → Q 置 1
    • J=0, K=0 → Q 保持
    • J=1, K=1 → Q 翻转
初版代码(存在 OUT 端口读回问题)
-- entity ENTITY jkff IS PORT( clk, j, k, clr, set : IN STD_LOGIC; q : OUT STD_LOGIC ); END ENTITY jkff; -- architecture(有问题:OUT 端口不能在进程内读取) ARCHITECTURE bhv OF jkff IS BEGIN PROCESS(clk, clr, set) BEGIN IF clr = '0' THEN -- 低有效异步清零 q <= '0'; ELSIF set = '0' THEN -- 低有效异步置位 q <= '1'; ELSIF (clk'EVENT AND clk = '1') THEN -- 上升沿 IF (j = '1' AND k = '0') THEN q <= '1'; ELSIF (j = '0' AND k = '1') THEN q <= '0'; ELSIF (j = '1' AND k = '1') THEN q <= NOT q; -- ❌ 错误:不能读取 OUT 端口 q ELSE q <= q; -- ❌ 错误:同上 END IF; END IF; END PROCESS; END ARCHITECTURE bhv;

问题:VHDL 中OUT端口在架构内部不可读(只能写)。q <= NOT qq <= q会编译报错。

两种修复方案

  1. OUT改为BUFFER(可读可写,但级联时需注意)
  2. 推荐:定义内部信号q1,进程内操作q1,进程外q <= q1
修正版(内部信号 + 进程外赋值)
-- Library and package LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- entity ENTITY jkff IS PORT( clk, j, k, clr, set : IN STD_LOGIC; q : OUT STD_LOGIC ); END ENTITY jkff; -- architecture ARCHITECTURE bhv OF jkff IS SIGNAL q1 : STD_LOGIC; -- 内部信号,可在进程内读写 BEGIN PROCESS(clk, clr, set) BEGIN IF clr = '0' THEN q1 <= '0'; ELSIF set = '0' THEN q1 <= '1'; ELSIF (clk'EVENT AND clk = '1') THEN IF (j = '1' AND k = '0') THEN q1 <= '1'; ELSIF (j = '0' AND k = '1') THEN q1 <= '0'; ELSIF (j = '1' AND k = '1') THEN q1 <= NOT q1; -- 翻转:读取的是 q1,合法 ELSE q1 <= q1; -- 保持 END IF; END IF; END PROCESS; q <= q1; -- ✅ 关键:进程外赋值,信号在此刻更新后驱动输出 END ARCHITECTURE bhv;

信号 vs 变量:变量:=立即生效;信号<=在进程挂起后才更新。因此输出映射必须放在PROCESS外部,或使用BUFFER端口。


五、计数器

5.1 八位加计数器

-- Library and package LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- entity ENTITY counter IS PORT( clk : IN STD_LOGIC; data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ); END ENTITY counter; -- architecture ARCHITECTURE bhv OF counter IS BEGIN PROCESS(clk) VARIABLE temp : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000"; BEGIN IF (clk'EVENT AND clk = '0') THEN -- 下降沿计数 temp := temp + 1; -- 变量立即 +1 data <= temp; -- 输出当前值 END IF; END PROCESS; END ARCHITECTURE bhv;

图说明:时钟源驱动clk,每来一个下降沿计数加 1,8 个 LED 以二进制显示data当前值。图中00001011= 十进制 11。


5.2 加减可控计数器

新增sub控制端:sub='0'加计数,sub='1'减计数,带溢出/下溢回绕。

-- entity ENTITY counter IS PORT( clk, sub : IN STD_LOGIC; data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ); END ENTITY counter; -- architecture ARCHITECTURE bhv OF counter IS BEGIN PROCESS(clk) VARIABLE temp : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000"; BEGIN IF (clk'EVENT AND clk = '0') THEN IF sub = '0' THEN -- 加计数,255 后回绕到 0 IF temp = "11111111" THEN temp := "00000000"; ELSE temp := temp + 1; END IF; ELSIF sub = '1' THEN -- 减计数,0 后回绕到 255 IF temp = "00000000" THEN temp := "11111111"; ELSE temp := temp - 1; END IF; END IF; data <= temp; END IF; END PROCESS; END ARCHITECTURE bhv;

图说明sub开关拨至 0 时递增,拨至 1 时递减。LED 阵列实时反映 8 bit 计数值。


5.3 带溢出标志、复位、重装载的完整计数器

-- entity ENTITY counter IS PORT( clk, sub, rst, load, clr_f : IN STD_LOGIC; number : IN STD_LOGIC_VECTOR(7 DOWNTO 0); flag : OUT STD_LOGIC; -- 溢出/下溢标志 data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ); END ENTITY counter; -- architecture ARCHITECTURE bhv OF counter IS BEGIN PROCESS(clk, rst, load, clr_f) VARIABLE temp : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000"; BEGIN IF clr_f = '1' THEN flag <= '0'; -- 清除溢出标志 ELSIF rst = '1' THEN temp := "00000000"; -- 同步复位 flag <= '0'; ELSIF load = '1' THEN temp := number; -- 加载预设值 ELSIF (clk'EVENT AND clk = '0') THEN IF sub = '0' THEN IF temp = "11111111" THEN temp := "00000000"; flag <= '1'; -- 向上溢出 ELSE temp := temp + 1; END IF; ELSE IF temp = "00000000" THEN temp := "11111111"; flag <= '1'; -- 向下溢出 ELSE temp := temp - 1; END IF; END IF; END IF; data <= temp; END PROCESS; END ARCHITECTURE bhv;

图说明:五个控制开关分别对应加减方向、复位、重装载、清标志;number为 8 bit 预置值总线。flag在计数溢出或下溢时置 1,需clr_f手动清除。


六、分频器与 PWM

6.1 2/4/8/16 分频

利用 4 bit 计数器各 bit 自然形成 2 的幂次分频:bit0 二分频,bit1 四分频,以此类推。

-- entity ENTITY freq IS PORT( clk, en : IN STD_LOGIC; f2, f4, f8, f16 : OUT STD_LOGIC ); END ENTITY freq; -- architecture ARCHITECTURE bhv OF freq IS BEGIN PROCESS(clk, en) VARIABLE count : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000"; BEGIN IF en = '1' THEN IF (clk'EVENT AND clk = '0') THEN count := count + 1; f2 <= count(0); -- ÷2 f4 <= count(1); -- ÷4 f8 <= count(2); -- ÷8 f16 <= count(3); -- ÷16 END IF; ELSE f2 <= '1'; f4 <= '1'; f8 <= '1'; f16 <= '1'; END IF; END PROCESS; END ARCHITECTURE bhv;

波形说明clk频率最高;f2每 2 个时钟翻转一次;f4每 4 个;f8每 8 个;f16每 16 个。各输出占空比均为 50%,频率依次为 clk 的 1/2、1/4、1/8、1/16。


6.2 十二分频freq12

-- entity ENTITY freq12 IS PORT( clk, en : IN STD_LOGIC; wave : OUT STD_LOGIC ); END ENTITY freq12; -- architecture ARCHITECTURE bhv OF freq12 IS BEGIN PROCESS(clk, en) VARIABLE count : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000"; BEGIN IF en = '0' THEN -- 低有效使能 IF (clk'EVENT AND clk = '1') THEN -- 上升沿计数 IF count = "0101" THEN -- 计数到 5 count := count + 1; wave <= '0'; -- 拉低输出 ELSIF count >= "1011" THEN -- 计数到 11 wave <= '1'; -- 拉高输出 count := "0000"; -- 复位计数器,完成 12 分频周期 ELSE count := count + 1; END IF; END IF; ELSE wave <= '1'; -- 禁用时输出高 END IF; END PROCESS; END ARCHITECTURE bhv;

波形说明en保持低电平有效时,wave在一个 12 时钟周期内产生固定宽度的低脉冲,实现非 2 的幂次分频。


6.3 PWM 脉宽调制

第一种:可调占空比
-- entity ENTITY PWM IS PORT( clk, en : IN STD_LOGIC; data : IN STD_LOGIC_VECTOR(3 DOWNTO 0); -- 占空比控制(0~15) wave : OUT STD_LOGIC ); END ENTITY PWM; -- architecture ARCHITECTURE bhv OF PWM IS BEGIN PROCESS(clk, en, data) VARIABLE count : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000"; BEGIN IF en = '1' THEN IF data = "1111" THEN wave <= '1'; -- 100% 占空比 ELSIF (clk'EVENT AND clk = '0') THEN count := count + 1; IF count < data THEN wave <= '1'; -- 计数小于 data:高电平 ELSE wave <= '0'; -- 否则低电平 END IF; END IF; ELSE wave <= '1'; END IF; END PROCESS; END ARCHITECTURE bhv;

图说明:4 bitdata决定每个周期内高电平持续的时钟数。data越小,占空比越低;data="1111"时输出恒为高。

第二种:可调占空比与周期

分别用nh(高电平持续时钟数)和nl(低电平持续时钟数)独立控制。

-- entity ENTITY pwm IS PORT( clk : IN STD_LOGIC; nh, nl : IN STD_LOGIC_VECTOR(3 DOWNTO 0); -- 高/低持续时间 wave : OUT STD_LOGIC ); END ENTITY pwm; -- architecture ARCHITECTURE bhv OF pwm IS BEGIN PROCESS(clk, nh, nl) VARIABLE count : STD_LOGIC_VECTOR(4 DOWNTO 0) := "00000"; BEGIN -- 边界条件处理 IF (nh = "0000" AND nl = "0000") THEN wave <= 'Z'; -- 高阻态 ELSIF nh = "0000" THEN wave <= '0'; -- 恒低 ELSIF nl = "0000" THEN wave <= '1'; -- 恒高 ELSIF (clk'EVENT AND clk = '0') THEN IF count >= ('0' & nh + nl - 1) THEN count := "00000"; -- 一个完整周期结束 wave <= '1'; ELSE IF count = (nh - 1) THEN wave <= '0'; -- 高电平阶段结束,转低 END IF; count := count + 1; END IF; END IF; END PROCESS; END ARCHITECTURE bhv;

波形说明:单个脉冲周期长度 =nh + nl个时钟,高电平占nh个、低电平占nl个。修改nh/nl可同时改变占空比和频率。


七、有限状态机(FSM)

7.1 基本四状态 RGB 控制器

最简单的 Moore 型状态机:状态在时钟上升沿切换,输出仅取决于当前状态。

-- Library and package LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- entity ENTITY rgb IS PORT( clk : IN STD_LOGIC; led : OUT STD_LOGIC_VECTOR(2 DOWNTO 0) -- RGB 三色,每 bit 驱动一色 ); END ENTITY rgb; -- architecture ARCHITECTURE bhv OF rgb IS TYPE state_type IS (s0, s1, s2, s3); SIGNAL state : state_type; BEGIN -- 状态转移进程(时序逻辑) PROCESS(clk) BEGIN IF (clk'EVENT AND clk = '1') THEN CASE state IS WHEN s0 => state <= s1; WHEN s1 => state <= s2; WHEN s2 => state <= s3; WHEN s3 => state <= s0; WHEN OTHERS => state <= s0; END CASE; END IF; END PROCESS; -- 输出逻辑进程(组合逻辑) PROCESS(state) BEGIN CASE state IS WHEN s0 => led <= "010"; -- 绿 WHEN s1 => led <= "011"; -- 黄 WHEN s2 => led <= "100"; -- 红 WHEN s3 => led <= "001"; -- 蓝 WHEN OTHERS => led <= "000"; END CASE; END PROCESS; END ARCHITECTURE bhv;

图说明:仅有时钟输入,每来一个上升沿状态循环 s0→s1→s2→s3→s0,RGB LED 依次变色。


7.2 完善版:八色可逆状态机

采用三段式写法:现态寄存器 → 次态逻辑 → 输出逻辑,并支持ddr方向控制与clr异步清零。

-- entity ENTITY rgb IS PORT( clk, ddr, clr : IN STD_LOGIC; -- ddr:方向控制(0 正向,1 反向) led : OUT STD_LOGIC_VECTOR(2 DOWNTO 0) ); END ENTITY rgb; -- architecture ARCHITECTURE bhv OF rgb IS TYPE state_type IS ( red, blue, green, yellow, purple, cyan, white, black ); SIGNAL current_state, next_state : state_type; BEGIN ---------------------------------------------------------------- -- 现态进程:状态寄存器 ---------------------------------------------------------------- cs : PROCESS(clk, clr) BEGIN IF clr = '1' THEN current_state <= black; -- 异步清零到 black ELSIF (clk'EVENT AND clk = '1') THEN current_state <= next_state; END IF; END PROCESS cs; ---------------------------------------------------------------- -- 次态进程:组合逻辑,决定下一状态 ---------------------------------------------------------------- ns : PROCESS(current_state, ddr) BEGIN CASE current_state IS WHEN black => IF ddr = '0' THEN next_state <= yellow; ELSE next_state <= blue; END IF; WHEN yellow => IF ddr = '0' THEN next_state <= purple; ELSE next_state <= black; END IF; WHEN purple => IF ddr = '0' THEN next_state <= cyan; ELSE next_state <= yellow; END IF; WHEN cyan => IF ddr = '0' THEN next_state <= white; ELSE next_state <= purple; END IF; WHEN white => IF ddr = '0' THEN next_state <= green; ELSE next_state <= cyan; END IF; WHEN green => IF ddr = '0' THEN next_state <= red; ELSE next_state <= white; END IF; WHEN red => IF ddr = '0' THEN next_state <= blue; ELSE next_state <= green; END IF; WHEN blue => IF ddr = '0' THEN next_state <= black; ELSE next_state <= red; END IF; WHEN OTHERS => next_state <= black; END CASE; END PROCESS ns; ---------------------------------------------------------------- -- 输出逻辑进程:Moore 型,输出只依赖现态 ---------------------------------------------------------------- ol : PROCESS(current_state) BEGIN CASE current_state IS WHEN red => led <= "100"; WHEN green => led <= "010"; WHEN blue => led <= "001"; WHEN white => led <= "111"; WHEN yellow => led <= "110"; WHEN cyan => led <= "011"; WHEN purple => led <= "101"; WHEN OTHERS => led <= "000"; -- black 及默认:全灭 END CASE; END PROCESS ol; END ARCHITECTURE bhv;

图说明

  • clk:驱动状态转移
  • ddr:切换颜色循环方向(0 正向:黑→黄→紫→…,1 反向)
  • clr:异步复位至 black(LED 全灭)
  • led[2:0]:分别驱动 R/G/B 通道

八、知识点速查

主题关键语法 / 概念
赋值信号<=(延迟更新);变量:=(立即更新)
进程PROCESS(敏感列表);时序逻辑放时钟边沿内
触发clk'EVENT AND clk='1'上升沿;'0'下降沿
复位同步:仅clk敏感;异步:控制信号加入敏感列表
端口OUT不可读;用内部SIGNAL或改BUFFER
多路选择嵌套IFCASE;向量用双引号
计数器VARIABLE做中间累加;注意溢出回绕
分频计数器 bit 输出 = 2^n 分频
PWM计数值与阈值比较;nh/nl 分别控制高/低时间
状态机现态寄存器 + 次态逻辑 + 输出逻辑(三段式)
http://www.cnnetsun.cn/news/3112674.html

相关文章:

  • RadiantQ jQuery Gantt Package
  • 视频剪辑智能体开发日志(Week 1)——从0开始搭建整个Pipeline
  • [Whirl节点]原理解析与实际应用
  • 2026年罗马尼亚EOR名义雇主服务商权威排行榜:揭晓五款精选五大方案
  • Claude Code:拉开新时代的差距
  • 鸿蒙原生应用开发实战:基于ArkTS构建智能记账助手的完整指南
  • 2026最新8款AI编程工具免费深度对比|学生党权威实测
  • Java 枚举类型三大实战场景详解
  • 2026最新2款学生党平替AI编程工具深度实测对比
  • 信道编码定理推导过程以及理论原理调研报告(P124302020向文杰)
  • 163MusicLyrics:网易云与QQ音乐歌词获取的完整解决方案
  • 还在手搓测试网DEX前端?OpenTools:拿来吧你!
  • 如何一键获取九大网盘真实下载链接?LinkSwift浏览器脚本终极指南
  • Android随笔-Binder缓冲区大小为什么远小于1M
  • 机器学习工程师的统计学实战手册:从数据诊断到模型解释
  • sp.net core + ef core 实现动态可扩展的分页方案
  • 无真实标签时如何评估模型性能:CBPE校准监控实战
  • MCP与Spring AI整合实战:云原生与AI技术融合指南
  • HunterPie终极指南:5分钟掌握《怪物猎人世界》最强数据覆盖层
  • FPGA与STM32的SPI通信 - FPGA主 STM32从
  • Android 7系统日志(五)日志读取—logcat源码深度分析
  • AI科研效率革命:用Claude技能包重构论文写作与数据分析流程
  • 海外短剧平台技术架构与运营实战指南
  • 本地部署AI Agent,6G显存跑Qwen3.6-35B-A3B 从入门到实战全流程
  • 科技融匠心!康姿百德学生床垫筑牢成长睡眠防线
  • 嵌套 H5 的跨端通信:iOS / Android / 小程序 / 浏览器
  • 第【48期】-- 通信问题的cvx教程之基础篇【一】-- MU-MIMO下行功率分配问题
  • Node.js Promise.all 并行查询实战:性能提升与错误处理详解
  • RAG 是什么?让大模型读懂私有知识库的关键技术
  • 多项式回归实战:用3阶曲线拟合替代线性模型