VHDL与数字系统EDA设计.docx
《VHDL与数字系统EDA设计.docx》由会员分享,可在线阅读,更多相关《VHDL与数字系统EDA设计.docx(20页珍藏版)》请在冰豆网上搜索。
![VHDL与数字系统EDA设计.docx](https://file1.bdocx.com/fileroot1/2023-1/24/886384ff-420d-4760-906f-f47e10656170/886384ff-420d-4760-906f-f47e106561701.gif)
VHDL与数字系统EDA设计
VHDL与数字系统EDA设计
姓名:
李勃
学号:
0800030014
班级:
代培生班
2009年6月20日
目录
实验一1
实验二5
实验三8
实验四10
实验五14
作业18
实验一
1.用IF语句设计一个四-十六译码器;
2.用CASE语句设计一个四-十六译码器;
3.用GENERATE语句构造一个串行的十六进制计数器。
实验目的:
学会使用相关EDA软件进行VHDL代码的输入、仿真,会用VHDL实现一些简单的组合逻辑和时序逻辑。
1.用IF语句设计一个四-十六译码器
实验方案:
接口信号的定义如下:
port(A:
inSTD_LOGIC;
B:
inSTD_LOGIC;
C:
inSTD_LOGIC;
D:
inSTD_LOGIC;
Y:
outSTD_LOGIC_VECTOR(15downto0)
);
enddecoder;
关键部分代码:
process(A,B,C,D)
variablecomb:
STD_LOGIC_VECTOR(3downto0);
begin
comb:
=A&B&C&D;
ifcomb="0000"thenY<="0000000000000001";
elsifcomb="0001"thenY<="0000000000000010";
elsifcomb="0010"thenY<="0000000000000100";
elsifcomb="0011"thenY<="0000000000001000";
elsifcomb="0100"thenY<="0000000000010000";
elsifcomb="0101"thenY<="0000000000100000";
elsifcomb="0110"thenY<="0000000001000000";
elsifcomb="0111"thenY<="0000000010000000";
elsifcomb="1000"thenY<="0000000100000000";
elsifcomb="1001"thenY<="0000001000000000";
elsifcomb="1010"thenY<="0000010000000000";
elsifcomb="1011"thenY<="0000100000000000";
elsifcomb="1100"thenY<="0001000000000000";
elsifcomb="1101"thenY<="0010000000000000";
elsifcomb="1110"thenY<="0100000000000000";
elsifcomb="1111"thenY<="1000000000000000";
elseY<="XXXXXXXXXXXXXXXX";
endif;
endprocess;
仿真验证:
仿真软件:
ActiveHDL7.1
2.用CASE语句设计一个四-十六译码器
实验方案:
接口信号的定义如下:
entitydecoder2is
port(
A:
inSTD_LOGIC_VECTOR(3downto0);
Y:
outSTD_LOGIC_VECTOR(15downto0)
);
enddecoder2;
关键部分代码:
process(A)
begin
caseAis
when"0000"=>Y<="0000000000000001";
when"0001"=>Y<="0000000000000010";
when"0010"=>Y<="0000000000000100";
when"0011"=>Y<="0000000000001000";
when"0100"=>Y<="0000000000010000";
when"0101"=>Y<="0000000000100000";
when"0110"=>Y<="0000000001000000";
when"0111"=>Y<="0000000010000000";
when"1000"=>Y<="0000000100000000";
when"1001"=>Y<="0000001000000000";
when"1010"=>Y<="0000010000000000";
when"1011"=>Y<="0000100000000000";
when"1100"=>Y<="0001000000000000";
when"1101"=>Y<="0010000000000000";
when"1110"=>Y<="0100000000000000";
when"1111"=>Y<="1000000000000000";
whenothers=>Y<="XXXXXXXXXXXXXXXX";
endcase;
endprocess;
仿真验证:
仿真软件:
ActiveHDL7.1
3.用GENERATE语句构造一个串行的十六进制计数器
实验方案:
接口信号的定义如下:
entitycounteris
port(
clk:
inSTD_LOGIC;
clr:
inSTD_LOGIC;
q:
outSTD_LOGIC_VECTOR(3downto0)
);
endcounter;
关键部分代码:
architecturertlofcounteris
componentdff
port(
d:
inSTD_LOGIC;
clr:
inSTD_LOGIC;
clk:
inSTD_LOGIC;
q:
outSTD_LOGIC;
qb:
outSTD_LOGIC
);
endcomponent;
signalq_in:
std_logic_vector(4downto0);
begin
q_in(0)<=clk;
G1:
foriin0to3generate
U0:
dffportmap(d=>q_in(i+1),clk=>q_in(i),clr=>clr,q=>q(i),qb=>q_in(i+1));endgenerate;
endrtl;
仿真验证:
仿真软件:
ActiveHDL7.1
实验二
设计一个两位二进制的加法器
实验目的:
学会设计简单的组合逻辑,并进行功能仿真。
实验方案:
先用基本逻辑门设计一个半加器,再用两个半加器组合成全加器,再用全加器设计成二进制加法器。
接口定义如下:
entitytwobit_adderis
port(
cin:
inSTD_LOGIC;
a:
inSTD_LOGIC_VECTOR(1downto0);
b:
inSTD_LOGIC_VECTOR(1downto0);
co:
outSTD_LOGIC;
s:
outSTD_LOGIC_VECTOR(1downto0)
);
endtwobit_adder;
关键部分代码:
半加器部分:
architecturehalf_adderofhalf_adderis
signalc,d:
std_logic;
begin
c<=aorb;
d<=anandb;
co<=notd;
s<=candd;
endhalf_adder;
全加器部分代码:
u0:
half_adderportmap(a,b,u0_s,u0_co);
u1:
half_adderportmap(u0_s,cin,s,u1_co);
co<=u0_cooru1_co;
二进制加法器部分代码:
u0:
full_adderportmap(a=>a(0),b=>b(0),cin=>cin,s=>s(0),co=>u0_co);
u1:
full_adderportmap(a=>a
(1),b=>b
(1),cin=>u0_co,s=>s
(1),co=>co);
仿真软件:
ActiveHDL7.1
2.设计一个两位的BCD计数器
实验目的:
学会设计简单的时序逻辑,并进行仿真。
实验方案:
先设计一个一位带进位的BCD计数器,再以它的进位输出作为十位计数器的时钟输入。
接口定义:
entityBCD_counteris
port(
clk:
inSTD_LOGIC;
clr:
inSTD_LOGIC;
q0:
outSTD_LOGIC_VECTOR(3downto0);
q1:
outSTD_LOGIC_VECTOR(3downto0)
);
endBCD_counter;
关键部分代码:
architecturertlofBCD_counteris
signalco:
std_logic;
signalin_q0,in_q1:
STD_LOGIC_VECTOR(3downto0);
begin
q0<=in_q0;
q1<=in_q1;
process(clk,clr)
begin
if(clr='1')then
in_q0<="0000";
elsif(clk'eventandclk='1')then
if(in_q0="1001")then
in_q0<="0000";
co<='1';
else
in_q0<=in_q0+'1';
co<='0';
endif;
endif;
endprocess;
process(co,clr)
begin
if(clr='1')then
in_q1<="0000";
elsif(co'eventandco='1')then
if(in_q1="1001")then
in_q1<="0000";
else
in_q1<=in_q1+'1';
endif;
endif;
endprocess;
endrtl;
仿真软件:
ActiveHDL7.1
实验三
利用数组形式描述256x8bits的RAM,并利用测试床完成对其读写操作。
实验目的:
学会简单随机存储器的读写操作,并利用测试台对其进行测试。
接口定义:
entityramis
generic(k:
integer:
=8;w:
integer:
=8);
port(
wr:
inSTD_LOGIC;
rd:
inSTD_LOGIC;
cs:
inSTD_LOGIC;
din:
inSTD_LOGIC_VECTOR(k-1downto0);
adr:
inSTD_LOGIC_VECTOR(w-1downto0);
dout:
outSTD_LOGIC_VECTOR(k-1downto0)
);
endram;
关键部分代码:
adr_in<=conv_integer(adr);
process(wr)
begin
if(wr'eventandwr='1')then
wr_rise<=now;
if(cs='1')then
sram(adr_in)<=dinafter2ns;
endif;
endif;
assert(wr_rise-din_change>=800ps)report"writesramsetuptimeviolation"severityWARNING;
endprocess;
process(rd,cs,adr_in,wr)
begin
if(rd='0'andcs='1')then
dout<=sram(adr_in)after3ns;
else
dout<=(others=>'Z')after4ns;
endif;
endprocess;
process(din)
begin
din_change<=now;
assert(din_change-wr_rise>300ps)report"readsramholdtimeviolation"severityWARNING;
endprocess;
仿真软件:
ActiveHDL7.1
实验四
用VHDL语言设计UART。
实验目的:
学会用VHDL语言设计复杂的电路。
实验方案:
UART主要有由数据总线接口、控制逻辑、波特率发生器、发送部分和接收部分等组成。
本设计主要设计UART中最重要的发送部分和接收部分,其他部分设计不在赘述。
功能包括发送缓冲器(tbr)、发送移位寄存器(tsr)、帧产生、奇偶校验、并转串、数据接收缓冲器(rbr)、接收移位寄存器(rsr)、帧产生、奇偶校验、串转并。
UART的帧格式下图所示:
UART发送器的设计
数据的发送是由微处理器控制,微处理器给出wrn信号,发送器根据此信号将并行数据din[7..0]锁存进发送缓冲器tbr[7..0],并通过发送移位寄存器tsr[7..0]发送串行数据至串行数据输出端sdo。
在数据发送过程中用输出信号tbre、tsre作为标志信号,当一帧数据由发送缓冲器tbr[7..0]送到发送发送移位寄存器tsr[7..0]时,tbre信号为1,而数据由发送移位寄存器tsr[7..0]串行发送完毕时,tsre信号为1,通知CPU在下个时钟装入新数据。
发送器端口信号如下图所示:
部分代码:
process(rst,wrn)--接收数据至tbr
begin
ifrst='1'then
tbr<=(others=>'0');
elsifwrn'eventandwrn='0'then
tbr<=din;
endif;
endprocess;
process(rst,clk16x,clk1x_enable)
begin
ifrst='1'then
clkdiv<="0000";
elsifclk16x'eventandclk16x='1'then
ifclk1x_enable='1'then
clkdiv<=clkdiv+"0001";
endif;
endif;
endprocess;
clk1x<=clkdiv(3);--产生clk1x时钟
process(rst,clk1x,no_bits_sent,tbr)
begin
ifrst='1'then
sdo<='1';
tsre<='1';
tsr<="00000000";
parity<='1';
elsifclk1x'eventandclk1x='1'then
ifstd_logic_vector(no_bits_sent)="0001"then
tsr<=tbr;--发送缓冲器tbr数据进入发送移位寄存器tsr
tsre<='0';--发送移位寄存器空标志置“0”
elsifstd_logic_vector(no_bits_sent)="0010"then
sdo<='0';--发送起始位信号“0”
elsifstd_logic_vector(no_bits_sent)>="0011"andstd_logic_vector(no_bits_sent)<="1010"then
tsr<=tsr(6downto0)&'0';--从低位到高位进行移位输出至串行输出端sdo
sdo<=tsr(7);
parity<=parityxortsr(7);--数据位中的1校验
endif;
endif;
endprocess;
process(rst,clk1x,clk1x_enable)--产生发送字符长度和发送次序计数器
begin
ifrst='1'orclk1x_enable='0'then
no_bits_sent<="0000";
elsifclk1x'eventandclk1x='1'then
ifclk1x_enable='1'then
no_bits_sent<=no_bits_sent+"0001";
endif;
endif;
endprocess;
UART接收器的设计
串行数据帧和接收时钟是异步的,发送来的数据由逻辑1变为逻辑0可以视为一个数据帧的开始。
接收器先要捕捉起始位,确定rxd输入由1到0,逻辑0要8个CLK16时钟周期,才是正常的起始位,然后在每隔16个CLK16时钟周期采样接收数据,移位输入接收移位寄存器rsr,最后输出数据dout。
还要输出一个数据接收标志信号标志数据接收完。
接收器的端口信号如下图所示:
部分代码:
process(clk1x,rst)
begin
ifrst='1'then
rsr<="00000000";
rbr<="00000000";
parity<='1';
framing_error<='0';
parity_error<='0';
elsifclk1x'eventandclk1x='1'then
ifstd_logic_vector(no_bits_rcvd)>="0001"andstd_logic_vector(no_bits_rcvd)<"1001"then---数据帧数据由接收串行数据端移位入接收移位寄存器
rsr(0)<=rxd2;
rsr(7downto1)<=rsr(6downto0);
parity<=parityxorrsr(0);
elsifstd_logic_vector(no_bits_rcvd)="1010"then
rbr<=rsr;--接收移位寄存器数据进入接收缓冲器
elsifparity='0'then
parity_error<='1';
elsifstd_logic_vector(no_bits_rcvd)="1001"andrxd2='0'then
framing_error<='1';
endif;
endif;
endprocess;
process(rst,clk1x,clk1x_enable,no_bits_rcvd)
begin
ifrst='1'or(std_logic_vector(no_bits_rcvd)="1100"andclk1x_enable='0')then
no_bits_rcvd<="0000";
elsifclk1x'eventandclk1x='1'then
ifclk1x_enable='1'then
no_bits_rcvd<=no_bits_rcvd+"0001";
endif;
endif;
endprocess;
dout<=std_logic_vector(rbr)whenrdn='0'else"ZZZZZZZZ";
end;
UART设计总模块
将发送器和接收器模块组装起来,就能较容易地实现通用异步收发器总模块。
总模块RTL图如下图:
程序在MAX+PLUSII环境下的分析
波形仿真图:
由于条件限制,数据给的太多,从上图是看不出来的,所以,为了说明设计的正确性,只给出了一个数据。
通过波形仿真图我们可以清楚的看到UART的工作原理。
实验五
完成第九章计时电路设计。
实验目的:
学会设计稍微复杂一点的电路,学会自顶向下的设计方法。
实验方案:
先进行十进制计数器,六进制计数器,四进制计数器等底层模块的设计,再运用模块化的设计方法,把它们组装成完整的计时器电路。
接口:
entitystop_watchis
port(
sysres:
inSTD_LOGIC;
reset_sw:
inSTD_LOGIC;
start_stop_sw:
inSTD_LOGIC;
clk:
inSTD_LOGIC;
dispen:
inSTD_LOGIC;
enclk:
inSTD_LOGIC;
xinxuanma:
outSTD_LOGIC;
segment:
outSTD_LOGIC_VECTOR(6downto0);
common:
outSTD_LOGIC_VECTOR(5downto0)
);
endstop_watch;
关键部分代码:
顶层模块的代码:
architecturertlofstop_watchis
componentclkgen
port(
sysres:
inSTD_LOGIC;
en1:
inSTD_LOGIC;
clk:
inSTD_LOGIC;
cntclk:
outSTD_LOGIC;
keyclk:
outSTD_LOGIC
);
endcomponent;
componentkeyin
port(
reset_sw:
inSTD_LOGIC;
start_stop_sw:
inSTD_LOGIC;
keyclk:
inSTD_LOGIC;
clk:
inSTD_LOGIC;
res:
outSTD_LOGIC;
stst:
outSTD_LOGIC
);
endcomponent;
componentctrl
port(
sysres:
inSTD_LOGIC;
res:
inSTD_LOGIC;
stst:
inSTD_L