4.1 优先编码器与七段译码器


4.1 优先编码器与七段译码器

本节摘要:编码器把多根输入线压缩成二进制码,译码器反过来把二进制码展开成多根输出线。本节完成一对方向相反的实战模块——八三优先编码器与七段数码管译码器,覆盖 case 兜底、优先级语义、段码真值表的推导方法。

需求先落地:按键怎么变成数字

给袖珍计算器原型定第一个需求:面板上有八个按键(编号零到七),任意时刻可能多个键同时按住(机械抖动、用户手滑),系统要输出"优先级最高的那个键"的二进制编码,同时点亮一个"有键按下"的指示。这是教科书里标准的八三优先编码器:八根输入、三根输出,加一根有效标志。

写代码之前先手工推优先级表——优先级规则定为"编号越大越优先"。八号键(下标七)按住时,无论其他键什么状态,输出就是 111。依次类推,只有零号键按住时输出 000。没有任何键时,输出给 000 但有效标志拉低,让下游知道这个 000 是"空"不是"零号键"。

图:编码与译码在计算器原型中的位置

图:编码与译码在计算器原型中的位置

写优先编码器:if 链的正确使用场景

上一章说过 if 链自带优先级——编码器要的正是这个:

library ieee; use ieee.std_logic_1164.all; entity prio_enc8 is port ( keys : in std_logic_vector(7 downto 0); -- key7 最高优先 code : out std_logic_vector(2 downto 0); -- 最高优先键的编号 valid : out std_logic -- 有键按下标志 ); end entity prio_enc8; architecture rtl of prio_enc8 is begin process (keys) begin valid <= '1'; -- 默认有键,下面逐级翻案 if keys(7) = '1' then code <= "111"; elsif keys(6) = '1' then code <= "110"; elsif keys(5) = '1' then code <= "101"; elsif keys(4) = '1' then code <= "100"; elsif keys(3) = '1' then code <= "011"; elsif keys(2) = '1' then code <= "010"; elsif keys(1) = '1' then code <= "001"; elsif keys(0) = '1' then code <= "000"; else code <= "000"; -- 无键:码无效,靠 valid 区分 valid <= '0'; end if; end process; end architecture rtl;

四个检查点。一,敏感表只有 keys,读过没有别的信号,配平。二,else 分支存在,code 在每条路径都被赋值,valid 同样,无锁存器。三,优先级顺序与书写顺序一致——keys(7) 写在最前,物理路径最短,语义与电路统一。四,"无键"与"零号键"输出码相同,靠 valid 区分——这是编码器的标准设计手法,接口上多花一根线,语义上消灭歧义。

写七段译码器:真值表驱动的 with-select

数码管有七段发光条,按 a 到 g 排布。共阴极管段线给高电平点亮;显示数字八要点亮 abcdef 六段(g 灭),显示数字一点亮 b、c 两段。把零到九、加上灭灯态,逐个画在方格纸上,得到完整段码表。落成代码用 with-select 最清爽:

library ieee; use ieee.std_logic_1164.all; entity seg7 is port ( digit : in std_logic_vector(3 downto 0); -- 0..9 seg : out std_logic_vector(6 downto 0) -- seg(6)=a … seg(0)=g,高电平点亮 ); end entity seg7; architecture rtl of seg7 is begin with digit select seg <= "1111110" when "0000", -- 0 "0110000" when "0001", -- 1 "1101101" when "0010", -- 2 "1111001" when "0011", -- 3 "0110011" when "0100", -- 4 "1011011" when "0101", -- 5 "1011111" when "0110", -- 6 "1110000" when "0111", -- 7 "1111111" when "1000", -- 8 "1111011" when "1001", -- 9 "0000000" when others; -- 非法输入全灭 end architecture rtl;

注意向量的位序约定:段 a 放在最高位还是最低位,纯看你画真值表时的定义——约定本身不重要,全工程一致才重要when others 兜住了十到十五这六个非法码,全灭处理,比点亮乱码友好。

上仿真:一眼扫完所有输入组合

组合电路的测试台可以暴力穷举——四位输入只有十六种组合,八位 keys 有二百五十六种,循环一把梭:

stim : process begin for k in 0 to 255 loop keys <= std_logic_vector(to_unsigned(k, 8)); wait for 10 ns; end loop; std.env.stop; end process;

跑完波形逐段检查:单键时码值正确;多键时输出编号最大者;全零时 valid 为低。段码部分重点抽查 0、1、8 三个值与灭灯态。穷举验证是组合电路的"满贯"考法——输入空间小,就不要漏考任何一个格子。

⚠️ 常见坑:段码位序约定混乱是上板黑屏的头号原因——代码里 a 在最高位、原理图里 a 接了低位引脚,显示出来的字全是"乱码"。定约时在代码注释里写死"哪一位是哪一段",上板前对照原理图核一遍。

💡 关键直觉:编码器与译码器是"多对一"与"一对多"的镜像。判断该用哪个,看数据流向:把多根线的信息压缩成编号,编码;把编号展开成多根控制线,译码。

本节要点回顾

  • 优先编码器用 if 链:书写顺序即优先顺序,物理路径与语义一致;
  • valid 标志消歧义:编码"空"与"零号"输出相同码时,接口必须能区分;
  • 译码器用 with-select 或 case:真值表直接落码,when others 兜非法值;
  • 位序约定写进注释:段码、按键映射的位序全工程统一,对照原理图核实;
  • 组合电路穷举验证:输入空间可控就全枚举,别抽样。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U