组合电路的 VHDL 设计 优先编码器 编码器(encoder) 也属于码制转换器一类 (BCD—1-out-of-10 ) ( p.49 表 2-9 ) 优先编码器属于多对 1 转换关系,没有一一对应关系,难 以采用上述方式描述; 74148 优先编码器真值表 见 p.278 表 5-23,表中含有大 量‘x ’项,目前 VHDL 还不能直接对其进行运算处理; 在 p.384 表 5-26 中,显示了行为设计的一种形式:采用 for-loop 语句; 也可以采用数据流设计中的条件代入语句实现: 例: 简化 74148 优先编码器的数据流设计 数据输入 i[7..0] 低电平有效 控制输入 el 低电平有效 数据输出 a[2..0] 反函数输出 library ieee; use ieee.std_logic_1164.all; entity kencoder is port (i: in std_logic_vector (7 downto 0); el: in std_logic; a: out std_logic_vector(2 downto 0)); end kencoder; architecture rtl of kencoder is signal a1:std_logic_vector(2 downto 0); begin a1 <="000" when i(7)= '0' else "001" when i(7 downto 6)="10" else "010" when i(7 downto 5)="110" else "011" when i(7 downto 4)="1110" else "100" when i(7 downto 3)="11110" else "101" when i(7 downto 2)="111110" else "110" when i(7 downto 1)="1111110" else "111"; a<=a1 when el='0' else "111"; end rtl; 奇偶校验电路 parity checker 奇偶校验电路是实现数据错误检验的一种基本电路,其方 式是检测在 9 位输入数据中‘1’的个数是奇数还是偶数; 3 输入端异或门可以看作 3 位奇偶校验电路: ‘1’的个数为奇数时输出为‘1’,为偶数时输出为‘0’ ; 利用该电路可以构成 9 位奇偶校验电路; p.418 表 5-47 9 位奇偶校验电路的行为设计 p.419 表 5-48 9 位奇偶校验电路的结构设计 例 9 位奇偶校验电路的数据流设计 library ieee; use ieee.std_logic_1164.all; entity kparity9 is port (i: in std_logic_vector ( 1 to 9); even,odd : out std_logic); end kparity9 ; architecture rtl of kparity9 is signal y1,y2,y3,y: std_logic; begin y1<= i(1) xor i(2) xor i(3) ; y2<= i(4) xor i(5) xor i(6) ; y3<= i(7) xor i(8) xor i(9) ; y<= y1 xor y2 xor y3 ; odd<= y ; even<= not y; end rtl; 运算电路 运算电路主要包括比较器 ( comparator) 、 加法器 ( add) 、 乘法器(multipliers ) 和算术逻辑单元(ALU ) 等电路。 在运算电路中,运算量经常需要进行算术运算; 在 VHDL 中,算术运算不能对 bit 、 std_logic 、 std_logic_vector 等类型进行; 此外,二进制的数值表达方式本身也存在符号表达方式 问题,不同表达方式的运算规则不同; 为了解决类型与运算的相容问题,统一符号运算问题, 在包集合 IEEE.std_logic_arith 中,定义了 signed 和 unsinged 两种类型,以及与这两种类型相应的转换函数和对这些类型 进行的运算,其规则如下(针对加/ 减运算): 若运算量中存在 signed 类型,结果就为 signed 类型;否 则为 unsinged 类型; 若结果被指定为 std_logic、 std_logic_vector 等类型,则 signed 或 unsigned 类型的结果自动转为指定类型; 运算结果的长度为最长运算量的长度,但若 unsigned 类 型与 signed 类型运算,会自动变为后一类型,其长度会增加 1 以在最高位增加符号位'0'; 对于通常所用的 sdt_logic_vector 类型的数据 d,需要进 行算术运算时,可以采用函数 signed(d)将其转换为 signed 类 型,或采用函数 unsigned(d)将其转换为 unsigned 类型,运算 完毕后,通过代入语句将结果直接赋值给 sdt_logic_vector 类 型的信号,即可恢复通用的类型; 例 P.445 表 5-55 各种运算结果的类型 8位不同类型数据的加/ 减法器 数据流设计 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity vadd is port (a,b: in unsigned( 7 downto 0 ); c : in signed ( 7 downto 0 ); d : in std_logic_vector( 7 downto 0 ); s : out unsigned (8 downto 0); t : out signed (8 downto 0); u : out signed (7 downto 0); v : out std_logic_vector(8 downto 0)); end vadd; architecture rtl of vadd is begin s <= ('0' & a)+('0' & b); t <= a+c; u <= c+signed(d); v <= c-unsigned(d); end rtl; 例 p.446 表 5-56 可选输入的加法器 数据流设计,采用条件代入语句 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity vaddshr is port (a,b,c,d: in signed( 7 downto 0 ); sel : in std_logic; s : out signed (7 downto 0)); end vaddshr; architecture rtl of vaddshr is begin s <= a+b when sel='1' else c+d; end rtl; 以上输入和输出均采用 signed 类型;在实际应用中,数 据传递采用统一的 std_logic 类型比较方便,因此在端口信号 中最好全都采用 std_logic 类型,由此会要求程序进行相应改 变。 例 采用 std_logic 类型端口的 8 位加法器 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity vadd is port (a,b: in std_logic_vector( 7 downto 0 ); c : in std_logic; s : out std_logic_vector(8 downto 0)); end vadd; architecture rtl of vadd is signal d: std_logic_vector(0 to 0); begin d(0)<= c; s <= ('0' & unsigned(a)) +unsigned(b)+unsigned(d); end rtl; 注意:由于 unsigned()函数只针对数组,因此不能将 c 直 接变化,必须先将其写为数组信号;此外,为了使 s 的数据 宽度能够与右端运算匹配,应先将 a 的宽度扩展到 8 位。 例 p.453 表 5-60 8 位乘法器的设计 数据流设计 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity vmul8x8i is port (x,y: in std_logic_vector( 7 downto 0 ); p : out std_logic_vector (15 downto 0)); end vmul8x8i; architecture rtl of vmul8x8i is begin p <= unsigned(x)*unsigned(y); end rtl; 例 p.428 表 5-50 8 位无符号数比较器的行为设计 library ieee; use ieee.std_logic_1164.all; entity vcompare is port (a,b: in std_logic_vector( 7 downto 0 ); eq,ne,gt,ge,lt,le: out std_logic); end vcompare; architecture beh of vcompare is begin process(a,b) begin eq <= '0';ne <= '0';gt <= '0';ge <= '0';lt <= '0';le <= '0'; if a=b then eq <= '1'; end if; if a/=b then ne <= '1'; end if; if a>b then gt <= '1'; end if; if a>=b then ge <= '1'; end if; if a<b then lt <= '1'; end if; if a<=b then le <= '1'; end if; end process; end beh; 算术逻辑单元 ALU 通过控制变量的选择,可以对输入的两组数据进行不同的算 术算或逻辑运算; 设计思想:将每一种运算设计为一个小程序块,通过选择语 句来选择实现; 例 带进位四位算术逻辑单元 ALU 设计 具有 3 位选择输入,可以实现 8 种不同的运算; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity alu1 is port(a,b: in unsigned(3 downto 0); cin: in std_logic; sel: in std_logic_vector(2 downto 0); y: out std_logic_vector(3 downto 0); cout: out std_logic); end alu1; architecture beh of alu1 is signal c: std_logic_vector(3 downto 0); begin process(a,b,cin,sel) begin case sel is when "000" => y(0)<= a(0) xor b(0) xor cin; -- 实现 a+b+cin; c(0)<= (a(0) and b(0)) or (a(0) and cin) or (cin and b(0)); gen1:for i in 1 to 3 loop y(i)<= a(i) xor b(i) xor c(i-1); c(i)<= (a(i) and b(i)) or (a(i) and c(i-1)) or (c(i-1) and b(i)); end loop; cout<=c(3); when "001" => y(0)<= a(0) xor b(0) xor cin; --实现 a-b-cin; c(0)<= (not a(0) and b(0)) or (not a(0) and cin) or (cin and b(0)); gen2:for i in 1 to 3 loop y(i)<= a(i) xor b(i) xor c(i-1); c(i)<= (not a(i) and b(i)) or (not a(i) and c(i-1)) or (c(i-1) and b(i)); end loop; cout<=c(3); when "010" => if cin='0' then y<= a(3)&a(2)&a(1)&a(0); --实现 a+cin; else y<=a+1; end if; cout<='0'; when "011" => if cin='0' then y<= a(3)&a(2)&a(1)&a(0); --实现 a-cin; else y<=a-1; end if; cout<='0'; when "100" => y(3)<=a(3) and b(3);y(2)<=a(2) and b(2); --实现 a and b; y(1)<=a(1) and b(1);y(0)<=a(0) and b(0); cout<='0'; when "101" => y(3)<=a(3) or b(3);y(2)<=a(2) or b(2); --实现 a or b; y(1)<=a(1) or b(1);y(0)<=a(0) or b(0); cout<='0'; when "110" => y(3)<=a(3) xor b(3);y(2)<=a(2) xor b(2); --实现 a xor b; y(1)<=a(1) xor b(1);y(0)<=a(0) xor b(0); cout<='0'; when "111" => y(3)<=not a(3);y(2)<=not a(2); --实现 not a; y(1)<=not a(1);y(0)<=not a(0); cout<='0'; when others =>y<= "0000"; cout<='0'; end case; end process; end beh; a 和 b 是 unsigned 的数组类型,进行算术运算后结果可 以直接赋给 std_logic_vector 类型(默认类型转换),不经过 运算或经过逻辑运算后不能直接赋值给 std_logic_vector 类 型;但一位的 unsigned 类型进行逻辑运算后结果可以直接赋 给 std_logic 类型(默认类型转换) 。 作业: 设计 p.441 表 5-53 所示的算术逻辑单元的结构体;已知实体 为: entity kalu is port( a, b : in std_logic_vector(3 downto 0); cin : in std_logic_vector; s : in std_logic_vector(2 downto 0); y : out std_logic_vector(3 downto 0)); end kalu; 习题: 5.57 对图 X5.57 的电路 (可控 2-4 译码器) 进行行为设计(采 用进程和 case 语句) ; 5.59 数据选择器 74153 的功能表如表 5-36 所示,写出该电 路的数据流设计;