组合电路的 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 所示,写出该电
路的数据流设计;