控制器设计 精品.docx
《控制器设计 精品.docx》由会员分享,可在线阅读,更多相关《控制器设计 精品.docx(18页珍藏版)》请在冰豆网上搜索。
控制器设计精品
实验报告
实验课程:
计算机组成原理I
实验日期:
20XX年11月15日,交报告日期:
20XX年12月2日
同组学生
姓名
学号
20XX07063
20XX07061
一、实验课题
按照题目要求设计计算机控制器的基本逻辑(不包括微操作信号产生电路),决定外部的端口(名称、有效电平)和内部各元件的连接,画出系统框图和逻辑图,设计仿真数据,用VHDL编程和仿真。
实验内容:
用层次结构设计的方法设计控制器的指令部件。
下层元件的设计已经在实验3中完成。
包括:
程序计数器、指令寄存器、数据寄存器、地址寄存器、指令译码器等。
本实验只需要做顶层设计。
顶层设计
功能要求:
具有控制器的部分基本功能,能够控制取指令操作、控制访存取数据操作、控制访存存数据操作、指令译码,等。
取指令机器周期:
把程序计数器的内容送到地址总线,延迟一段时间后把从存储器中读出的指令(通过数据总线读入),送到指令寄存器;每取一个指令字程序计数器加1。
取数据机器周期:
把地址寄存器的内容送到地址总线,延迟一段时间后把从存储器中读出的数据(通过数据总线)送到数据寄存器。
存数据机器周期:
把地址寄存器的内容送到地址总线,把数据寄存器中的数据送到数据总线,延迟一段时间后结束。
指令译码:
假设操作码在指令字的最高3位。
提示1:
控制器内部数据通路,可以是总线结构,也可以是直接连接结构。
提示2:
控制器与系统总线的连接方法,有两种结构可以考虑:
①程序计数器、指令寄存器、数据寄存器、地址寄存器都与系统总线有直接连接。
②只有数据寄存器和地址寄存器与系统总线连接。
程序计数器和指令寄存器不与系统总线连接。
程序计数器内容必须先送到地址寄存器,然后才能到地址总线。
从存储器中读出的指令必须先送到数据寄存器,然后才能到指令寄存器。
仿真
设计仿真波形数据,模拟取指令、访存取数据、访存存数据等操作。
要考虑到所有可能的情况。
在实验报告中必须清楚说明仿真波形数据是怎样设计的。
二、逻辑设计
控制器系统框图
端口说明:
Loadq,loadd:
数据寄存器的同步置数端口
Loada:
地址寄存器的同步置数端口
Loadi:
指令寄存器的同步置数端口
zq,zd;数据寄存器的三态控制端口
Clk:
时钟信号
Zpc:
程序计数器的三态控制端口
Za:
地址寄存器的三态控制端口
ld:
程序计数器的同步置数端口
r:
程序计数器的同步清零端口
et:
程序计数器的加1控制端口
cot:
cot(0),cot
(1)分别控制数据寄存器和程序计数器向地址寄存器和指令寄存器的数据传送
qd:
数据的双向输入输出端口(连接系统数据总线)数据从外部先送到系统总线才可以送到数据寄存器
da:
地址寄存器输出端口(连接系统地址总线)
ic:
经过译码器输出的控制信号
d:
程序计数器的置数端口。
控制器逻辑图
三、VHDL源程序
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
--ContolUnit
entitycontrol_unitis
port
(
--loadd,loadq,loada,loadi同步置数端口高电平有效
--zq,zd三态控制端口,低电平有效
--zpc,za三态控制端口,高电平有效
--clk时钟信号,上升沿有效
--ld程序计数器的预置数端口,低电平有效
--r程序计数器的清零端口,低电平有效
--et控制程序计数器自动加1功能
--qd数据从内存读出数据后送入系统总线的输入端,也是输出端口
--ic译码器的输出端口,即:
控制信号。
--cot是控制数据在寄存器间传输的信号
--cot(0)控制DR到IR的数据流通
--cot
(1)控制程序计数器到AR的数据流通
--d程序计数器的输入端口
loadd,loadq,loada,loadi,zq,zd,clk,ld,r,et,za,zpc:
instd_logic;
cot:
instd_logic_vector(1downto0);
qd:
inoutstd_logic_vector(7downto0);
d:
inunsigned(7downto0);
ic:
outstd_logic_vector(7downto0);
qa:
outstd_logic_vector(7downto0)
);
endcontrol_unit;
architecturebehaveofcontrol_unitis
--数据总线和地址总线
--signalABUS:
std_logic_vector(7downto0);
--signalDBUS:
std_logic_vector(7downto0);
--引用地址寄存器
ponentaddress_register
port
(
--load同步并行置数
--z三态输出z=1isvalidesignal
--d输入
--q输出
load,z,clk:
instd_logic;
d:
instd_logic_vector(7downto0);
q:
outstd_logic_vector(7downto0)
);
endponent;
--引用数据寄存器
ponentdata_register
port
(
--clk时钟信号
--zq控制q端口的三态
--zd控制d端口的三态
--load1,load2同步并行置数.loadd控制d,loadq控制q
--d输入输出双向端口
--q输入输出端口
clk,zd,zq,loadd,loadq:
instd_logic;
d:
inoutstd_logic_vector(7downto0);
q:
inoutstd_logic_vector(7downto0)
);
endponent;
--引用译码器
ponentdecode
port
(
A:
instd_logic_vector(2downto0);--输入
Y:
outstd_logic_vector(7downto0)--输出
);
endponent;
--引用程序计数器
ponenteight_count
port
(
--et控制自动加1的端口
--clk时钟信号
--c进位输出
--z三态们z=1
--ld预制数控制端ld=0
--r同步清零端r=0有效
et,clk,z,ld,r:
instd_logic;
c:
outstd_logic;
d:
inunsigned(7downto0);
q:
outunsigned(7downto0)
);
endponent;
--引用指令寄存器
ponentinstruction_register
port
(
clk,load:
instd_logic;
d:
instd_logic_vector(7downto0);
q:
outstd_logic_vector(7downto0)
);
endponent;
--在程序计数器和地址寄存器之间的内部信号
signalpcdr:
std_logic_vector(7downto0);
signalUSpcdr:
unsigned(7downto0);
--在数据寄存器到指令寄存器之间的内部信号
signaldrir:
std_logic_vector(7downto0);
signaldeir:
std_logic_vector(7downto0);
---暂存信号
signalt1:
std_logic_vector(7downto0);
signalt2:
std_logic_vector(7downto0);
signalt3:
std_logic_vector(7downto0);
begin
P1:
process(cot)
begin
ifcot
(1)='0'then
t1<=(others=>('Z'));
elset1<=pcdr;
endif;
ifcot(0)='0'then
t2<=(others=>('Z'));
elset2<=drir;
endif;
endprocess;
--实例化程序计数器,
PC:
eight_countportmap
(clk=>clk,z=>zpc,et=>et,d=>d,ld=>ld,r=>r,q=>USpcdr);
--convertunsigneddatatostd_logic_vector;
pcdr<=conv_std_logic_vector(USpcdr,8);
--t1<=cot
(1)andpcdr;
--实例化地址寄存器
AR:
address_registerportmap
(clk=>clk,z=>za,load=>loada,d=>t1,q=>qa);
--实例化数据寄存器
DR:
data_registerportmap
(clk=>clk,zq=>zq,zd=>zd,loadd=>loadd,loadq=>loadq,q=>qd,d=>drir);
--实例化指令寄存器
IR:
instruction_registerportmap
(clk=>clk,load=>loadi,d=>t2,q=>deir);
--实例化译码器
DE:
decodeportmap
(A=>deir(7downto5),Y=>ic);
endbehave;
--address_register
libraryieee;
useieee.std_logic_1164.all;
entityaddress_registeris
port
(
--load同步并行置数
--z三态输出z=1isvalidesignal
--d输入
--q输出
load,z,clk:
instd_logic;
d:
instd_logic_vector(7downto0);
q:
outstd_logic_vector(7downto0)
);
endaddress_register;
architecturebehaveofaddress_registeris
signaliq:
std_logic_vector(7downto0);
begin
process(clk,z,load)
begin
ifrising_edge(clk)andload='1'then
iq<=d;
endif;
ifz='1'then
q<=(others=>'Z');
else
q<=iq;
endif;
endprocess;
endbehave;
--dataregister
libraryieee;
useieee.std_logic_1164.all;
entitydata_registeris
port
(
--clk时钟信号
--zq控制q端口的三态
--zd控制d端口的三态
--load1,load2同步并行置数.loadd控制d,loadq控制q
--d输入输出双向端口
--q输入输出端口
clk,zd,zq,loadd,loadq:
instd_logic;
d:
inoutstd_logic_vector(7downto0);
q:
inoutstd_logic_vector(7downto0)
);
enddata_register;
architecturebehaveofdata_registeris
signaliq:
std_logic_vector(7downto0);
begin
process(clk,zd,zq,loadd,loadq)
begin
ifrising_edge(clk)then
ifloadd='1'andzd='0'then--因为d是双向端口,当d作为输入端口时,
--d作为输出端口时应该是高阻态,否则会产生线与
iq<=d;
d<=(others=>'Z');
endif;
ifloadq='1'andzq='0'then
iq<=q;
q<=(others=>'Z');
endif;
endif;
ifzd='0'then--三态门关闭
d<=(others=>'Z');
elsed<=iq;
endif;
ifzq='0'then--三态门关闭
q<=(others=>'Z');
elseq<=iq;
endif;
endprocess;
endbehave;
--Decode
libraryieee;
useieee.std_logic_1164.all;
entitydecodeis
port
(
A:
instd_logic_vector(2downto0);--输入
Y:
outstd_logic_vector(7downto0)--输出
);
enddecode;
architecturede_behaveofdecodeis
signals:
std_logic;
begin
process(A)
begin
caseAis
when"000"=>Y<="11111110";
when"001"=>Y<="11111101";
when"010"=>Y<="11111011";
when"011"=>Y<="11110111";
when"100"=>Y<="11101111";
when"101"=>Y<="11011111";
when"110"=>Y<="10111111";
when"111"=>Y<="01111111";
endcase;
endprocess;
endde_behave;
--eight_count
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
entityeight_countis
port
(
--et控制自动加1的端口
--clk时钟信号
--c进位输出
--z三态们z=1
--ld预制数控制端ld=0
--r同步清零端r=0有效
et,clk,z,ld,r:
instd_logic;
c:
outstd_logic;
d:
inunsigned(7downto0);
q:
outunsigned(7downto0)
);
endeight_count;
architecturebehaveofeight_countis
signaliq:
unsigned(7downto0);
begin
process(clk,et,z,ld,r)
begin
ifrising_edge(clk)then
ifr='0'then--同步清零
iq<=(others=>'0');
elsifld='0'theniq<=d;--预制数
elsifet='1'theniq<=iq+1;--计数
endif;
endif;
ifiq=255thenc<='1';--计数到255,产生进位
elsec<='0';
endif;
q<=iq;
ifz='1'then--三态们关闭
c<='Z';
q<=(others=>'Z');
endif;
endprocess;
endbehave;
libraryieee;
useieee.std_logic_1164.all;
entityinstruction_registeris
port
(
clk,load:
instd_logic;
d:
instd_logic_vector(7downto0);
q:
outstd_logic_vector(7downto0)
);
endinstruction_register;
architecturebehaveofinstruction_registeris
signalsave:
std_logic_vector(7downto0);
begin
process(clk,load)
begin
ifrising_edge(clk)andload='1'then
save<=d;
endif;
q<=save;
endprocess;
endbehave;
四、仿真设计
由于元器件的仿真在实验3中已经做过,所以此处不再进行元器件的仿真。
首先令clk每隔10纳秒翻转一次。
et=1(有效),ld=1(无效),r=1(无效)
这是程序计数器处于工作状态。
取指令:
在第三个时钟上升沿时,zpc=0,(程序计数器三态门打开),loada=1(地址寄存器同步控制端有效),za=0(地址寄存器三态门打开),Cot
(1)=1(让pc输出的数据传入地址寄存器),这是输出应该是00000010,因为程序计数器刚好计数三个。
访存取指令:
下一个时钟上升沿时.
qd=11111111,zq=0,zd=1,loadq=1,loadd=0.za=1,zpc=1,loada=0,loadi=1,cot(0)=1
下一个时钟上升沿时:
zd=1(数据寄存器的三态门打开),loadi=1(指令寄存器的同步置数端口有效),cot=’01’(让数据寄存器里的数据传入指令寄存器)。
结果ic输出的应该是qd的高三位对应的指令控制信号011111111.
访存存数据:
下一个时钟上升沿:
Zq=1,其它信号都处于无效状态。
这是数据寄存器的三态门打开,数据送到系统总线,然后存入存储器。
输出的应该是先前存入的数据11111111
验证cot的有效性:
下二个时钟上升沿:
za=0,zpc=0,loada=1,cot分别等于00和10以验证控制数据传入的信号的有效性。
五、结果分析讨论
从图中可以看出,当没有置数之前,ic的值是111111110,,那是因为软件默认传入A端口的值是000,从qa的第一变化开始出也可以看出,za=0三态门打开的时候在时钟上升沿来到之前qa由ZZZZZZZZ变为00000000中也可以得到佐证。
时钟上升沿来到的时候,za的三态门是打开的,于是就把其中的地址输出,00000010,,正好是第三次时钟上升沿应该有的数据。
然后,从qd植入数据11111111,虽然数据寄存器到总线的三态门是关闭的qd输入却是置入的数据,这是正确的。
因为输入输出端口是一个端口,在此时此刻就应该显示qd置入的数据。
然后把数据寄存器中保存的指令,传入指令寄存器,得到输出结果01111111。
这真是译码器中的111对应的输出。
然后zq的三态门打开,数据寄存器中的数据送到系统总线,显示的是上一次置入的数据。
此系统总线上的数据可以送到存储器中。
然后验证cot的有效性,从图中的可以看出,两次时钟上升沿中,第一次由于cot处于无效状态qa的输出是高组态(虽然三态门已经打开),而后一次,由于cot处于有效状态,qa输出的是第九次时钟上升沿的数据00001000
这一副图也是验证cot有效性的。
但它是验证数据寄存器和指令寄存器之间的cot的有效性的。