硬件基础实验二 实验报告
一、指令集结构
该模型机要实现以下指令:
|
|
指令格式 |
功能 |
装载存储指令 |
LDA |
0x20 Byte |
R5<-Mem[Byte] |
STA |
0x40 Byte |
Mem[Byte]<-R5 |
|
运算指令 |
ADD |
0xC0 Byte |
R5<-R5 加 Mem[Byte] |
AND |
0xE0 Byte |
R5<-R5 与 Mem[Byte] |
|
COM |
0x80 |
R5<-取反R5 |
|
传输指令 |
OUT |
0x60 Byte |
BUS<-Mem[Byte] |
跳转指令 |
JMP |
0xA0 Byte |
PC<-Mem[Byte] |
二、微程序流程
三、模型机微体系结构
四、设计思路
依据微体系结构图通过VHDL编程设计模型机,由模型机主题、时序电路、数码管显示模块组成。
地址转移逻辑:
INPUT:T4、CLR、SWE、SRD、IR[2..0]、P1、Addr[4..0]、 | OUTPUT:A[4..0] |
CLR=0 | 异步清零,用于产生主入口地址00000 |
SWE=0 | A[4]异步强置1,用于产生RAM强写入口地址10000 |
SRD=0 | A[3]异步强置1,用于产生RAM强读入口地址01000 |
T4↑,P1=0 | 根据下址顺序执行,A[4..0]=Addr[4..0] |
T4↑,P1=1 | 重新映射,A[4..0]=Addr[4..3]&IR[2..0] |
五、设计模型机主体
用VHDL代码实现
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity microcomputer is
port( Clr,srd,swe,t1,t2,t3,t4:in std_logic;
sw_in:in std_logic_vector(7 downto 0);
mpcout:out std_logic_vector(4 downto 0);
arout,bus_data:out std_logic_vector(7 downto 0));
end microcomputer;
architecture rtl of microcomputer is
type RAM is array(0 to 31)of std_logic_vector(7 downto 0); --32*8 RAM
signal ram8:RAM:=(x"20",x"0d",x"c0",x"0e",x"40",x"10",x"60",x"10",x"e0",x"0f",x"80",
x"a0",x"00",x"55",x"8a",x"f0",x"ff",others=>x"00"); --初始化RAM
signal pc,ar,dr1,dr2,r5,bus_Reg,bus_reg_t2,bus_Reg_t3:std_logic_vector(7 downto 0);
signal mpc,mpc_t2,mpc_t3,mpc_t4:std_logic_vector(4 downto 0);
signal ir:std_logic_vector(2 downto 0);
begin
mpcout<=mpc_t4;
arout<=ar;
bus_data<=bus_Reg;
ct1:process(t1,Clr,srd,swe)
begin
if Clr='0' then mpc<=(others=>'0');
elsif swe='0' then mpc<="10000";
elsif srd='0' then mpc<="01000";
elsif t1='1' and t1'event then mpc<=mpc_t4;
end if;
end process;
ct2:process(t2,mpc,sw_in,ar,Clr)
begin
if Clr='0' then mpc_t2<=(others=>'0');
elsif t2='1' and t2'event then
case mpc is
when "00000"=>mpc_t2<="00001";bus_Reg_t2<=sw_in;
when "00001"=>mpc_t2<="00010";bus_Reg_t2<=pc;
when "00010"=>mpc_t2<="01000";bus_Reg_t2<=ram8(conv_integer(ar));
when "01001"=>mpc_t2<="10101";bus_Reg_t2<=pc;--lda
when "10101"=>mpc_t2<="10110";bus_Reg_t2<=ram8(conv_integer(ar));
when "10110"=>mpc_t2<="00001";bus_Reg_t2<=ram8(conv_integer(ar));
when "01010"=>mpc_t2<="10111";bus_Reg_t2<=pc;--sta
when "10111"=>mpc_t2<="11000";bus_Reg_t2<=ram8(conv_integer(ar));
when "11000"=>mpc_t2<="00001";bus_Reg_t2<=r5;ram8(conv_integer(ar))<=r5;
when "01011"=>mpc_t2<="11001";bus_Reg_t2<=pc;--out
when "11001"=>mpc_t2<="11010";bus_Reg_t2<=ram8(conv_integer(ar));
when "11010"=>mpc_t2<="00001";bus_Reg_t2<=ram8(conv_integer(ar));
when "01100"=>mpc_t2<="11011";dr1<=r5;bus_Reg_t2<=r5;
when "11011"=>mpc_t2<="00001";bus_Reg_t2<=bus_Reg_t2;
when "01101"=>mpc_t2<="11100";bus_Reg_t2<=pc;
when "11100"=>mpc_t2<="00001";bus_Reg_t2<=ram8(conv_integer(ar));
when "01110"=>mpc_t2<="00011";bus_Reg_t2<=pc;
when "00011"=>mpc_t2<="00100";bus_Reg_t2<=ram8(conv_integer(ar));
when "00100"=>mpc_t2<="00101";dr2<=ram8(conv_integer(ar));bus_Reg_t2<=ram8(conv_integer(ar));
when "00101"=>mpc_t2<="00110";dr1<=r5;bus_Reg_t2<=r5;
when "00110"=>mpc_t2<="00001";bus_Reg_t2<=bus_Reg_t2;
when "01111"=>mpc_t2<="11101";bus_Reg_t2<=pc;
when "11101"=>mpc_t2<="11110";bus_Reg_t2<=ram8(conv_integer(ar));
when "11110"=>mpc_t2<="11111";dr2<=ram8(conv_integer(ar));bus_Reg_t2<=ram8(conv_integer(ar));
when "11111"=>mpc_t2<="00111";dr1<=r5;bus_Reg_t2<=r5;
when "00111"=>mpc_t2<="00001";bus_Reg_t2<=bus_Reg_t2;
when "10000"=>mpc_t2<="10001";bus_Reg_t2<=sw_in;
when "10001"=>mpc_t2<="10010";bus_Reg_t2<=pc;
when "10010"=>mpc_t2<="10001";bus_Reg_t2<=sw_in;ram8(conv_integer(ar))<=sw_in;
when "01000"=>mpc_t2<="10011";bus_Reg_t2<=sw_in;
when "10011"=>mpc_t2<="10100";bus_Reg_t2<=pc;
when "10100"=>mpc_t2<="10011";bus_Reg_t2<=ram8(conv_integer(ar));
when others=>mpc_t2<=mpc;bus_Reg_t2<=bus_Reg_t2;
end case;
end if;
end process;
ct3:process(t3,mpc,mpc_t2,bus_Reg_t2,Clr)
begin
if Clr='0' then mpc_t3<=(others=>'0');
elsif t3='1' and t3'event then
mpc_t3<=mpc_t2;
bus_Reg_t3<=bus_Reg_t2;
case mpc is
when "00000"=>pc<=bus_Reg_t2;
when "00001"=>ar<=bus_Reg_t2;pc<=pc+1;
when "00010"=>ir<=bus_Reg_t2(7 downto 5);
when "01001"=>ar<=bus_Reg_t2;pc<=pc+1;
when "10101"=>ar<=bus_Reg_t2;
when "10110"=>r5<=bus_Reg_t2;
when "01010"=>ar<=bus_Reg_t2;pc<=pc+1;
when "10111"=>ar<=bus_Reg_t2;
when "01011"=>ar<=bus_Reg_t2;pc<=pc+1;
when "11001"=>ar<=bus_Reg_t2;
when "11011"=>r5<=not dr1;bus_Reg_t3<=not dr1;
when "01101"=>ar<=bus_Reg_t2;pc<=pc+1;
when "11100"=>pc<=bus_Reg_t2;
when "01110"=>ar<=bus_Reg_t2;pc<=pc+1;
when "00011"=>ar<=bus_Reg_t2;
when "00110"=>r5<=dr1+dr2;bus_Reg_t3<=dr1+dr2;
when "01111"=>ar<=bus_Reg_t2;pc<=pc+1;
when "11101"=>ar<=bus_Reg_t2;
when "00111"=>r5<=dr1 and dr2;bus_Reg_t3<=dr1 and dr2;
when "10000"=>pc<=bus_Reg_t2;
when "10001"=>ar<=bus_Reg_t2;pc<=pc+1;
when "01000"=>pc<=bus_Reg_t2;
when "10011"=>ar<=bus_Reg_t2;pc<=pc+1;
when others=>bus_Reg_t3<=bus_Reg_t2;
end case;
end if;
end process;
ct4:process(Clr,t4,mpc,ir,mpc_t3)
begin
if Clr='0' then mpc_t4<=(others=>'0');
elsif t4='1' and t4'event then
bus_Reg<=bus_Reg_t3;
case mpc is
when "00010"=>mpc_t4<=mpc_t3(4 downto 3)&ir;
when others=>mpc_t4<=mpc_t3;
end case;
end if;
end process;
end rtl;
其中,进程ct1、ct2、ct3、ct4功能划分依据分别是:
ct1:微序列控制器下址跳转。
ct2:实现各种指令,主要集中在实现从存储器或者寄存器释放数据到总线上。
ct3:完成各种指令,从总线上装载数据到相应的存储器或者寄存器中。
ct4:生成下址,判断下址生成方式,根据不同的方式生成下址。
编译运行,仿真测试一下功能,正确无误后打包为bsf备用。
六、设计时序电路
通过状态机设计时序电路,如图:
将模型机产生的VHDL代码打包备用。
七、设计显示模块
通过VHDL代码实现数码管显示模块
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity scan_led4 is
port(
scan_clk:in std_logic;
arh,arl,bush,busl:in std_logic_vector(3 downto 0);
seg7:out std_logic_vector(6 downto 0);
bsg:out std_logic_vector(3 downto 0));
end scan_led4;
architecture rtl of scan_led4 is
signal seg_wire:std_logic_vector(3 downto 0);
signal bsg_wire:std_logic_vector(3 downto 0);
type st is (k1,k2,k3,k4); --四个状态,模4计数器
signal st_nxt:st; --st类型的信号?
--模4计数器
begin
scan_st:process(scan_clk,st_nxt)
begin
if(scan_clk'event and scan_clk='1') then
case st_nxt is
when k1=> st_nxt<=k2;
when k2=> st_nxt<=k3;
when k3=> st_nxt<=k4;
when k4=> st_nxt<=k1;
end case;
end if;
end process;
--段选和位选
scan_o:process(st_nxt,arh,arl,bush,busl)
begin
case st_nxt is
when k1=>
seg_wire<=arh;
bsg_wire<="1000"; --计数值1时,1号数码管显示ar高四位
when k2=>
seg_wire<=arl;
bsg_wire<="0100"; --计数值2时,2号数码管显示ar低四位
when k3=>
seg_wire<=bush;
bsg_wire<="0010"; --计数值3时,3号数码管显示bus高四位
when k4=>
seg_wire<=busl;
bsg_wire<="0001"; --计数值4时,4号数码管显示bus低四位
end case;
end process;
--7段译码
seg7<="1111110" when seg_wire=x"0" else
"0110000" when seg_wire=x"1" else
"1101101" when seg_wire=x"2" else
"1111001" when seg_wire=x"3" else
"0110011" when seg_wire=x"4" else
"1011011" when seg_wire=x"5" else
"1011111" when seg_wire=x"6" else
"1110000" when seg_wire=x"7" else
"1111111" when seg_wire=x"8" else
"1111011" when seg_wire=x"9" else
"1110111" when seg_wire=x"a" else
"0011111" when seg_wire=x"b" else
"0001101" when seg_wire=x"c" else
"0111101" when seg_wire=x"d" else
"1001111" when seg_wire=x"e" else
"1000111" when seg_wire=x"f" else
"0000000" ;
bsg<=bsg_wire;
end rtl;
仿真测试功能,正确无误后打包备用。
八、顶层组装
将各模块组装如图:
九、测试运行
IR[7..5]对应BUS(3,1,5),计算(C 加 D)’ and B’ 加 A
其中 A=01H B=02H C=03H D=04H分别存储在OEH至11H单元。
汇编代码如下:
00H: LDA 14H
02H: ADD 15H
04H: COM
05H: STA 16H --运算结果暂存在16H单元
07H: LDA 13H
09H: COM
0AH: AND 16H
0CH: ADD 12H
0EH: STA 16H
10H: JMP 17H
12H: 01H
13H: 02H
14H: 03H
15H: 04H
16H: XXH
17H: COM 16H
重新初始化RAM,写入上述程序:
signal ram8:RAM:=(x"20",x"14",x"0a",x"15",x"08",x"02",x"16",x"20",x"13",x"08",x"2a",
x"16",x"0a",x"12",x”02”,x”16”,x”28”,x”17”,x"01",x"02",x"03",x"04",x”00”,x”08”,x”16”,others=>x"00"); --初始化RAM
修改IR对应BUS:
when "00010"=>ir<=bus_Reg_t2(3)&bus_Reg_t2(1)&bus_Reg_t2(5);
下载测试,单步执行,观察AR,BUS上的值,最后计算出结果为F9H。
十、实验日志
1. bus_reg_t2<=ram8(conv_integer(ar))与ram8(conv_integer(ar))<=r5的含义:
1. 将ram8存储器中对应于ar中地址单元的数据取出来放到bus_reg_t2寄存器中。
1.将r5寄存器中的数据装载到ram8存储器中对应于ar中地址单元中。
2. 修改IR和BUS的对应关系时,总是报错,语法错误。后来才知道要用并置语句,修改成:ir<=bus_Reg_t2(3)&bus_Reg_t2(1)&bus_Reg_t2(5);
关于并置语句:
并置“&” 就是用来进行位和位矢量的连接运算 所谓位和位矢量的连接运算是指将并置操作符右边的内容接在左边的内容之后以形成一个新的位矢量.通常采用并置操作符进行连接的方式很多 : 既可以将两个位连接起来形成一个位矢量 , 也可以将两个位矢量连接起来以形成一个新的位矢量 , 还可以将位矢量和位连接起来形成一个新的矢量。
3. 关于type语句
type st is (k1,k2,k3,k4); --四个状态,模4计数器
意思是定义一个数据类型state具有4种状态k1,k2,k3,k4可以像定义其他类型一样定义这种数据类型,一般用于状态机
4. 关于数码管显示的VHDL设计
这次的代码从整体上设计数码管显示电路,比硬件一时分模块写VHDL代码然后打包在组装方便了很多,还有模型机主体的设计,较之分模块整合更加方便,让我感受到VHDL编程给设计带来的便利。
5. 声明时库资源同时声明三个
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
他们指定singned和unsigned数据类型和相应的算术与比较操作。它可以包含有几个数据转换函数,允许数据从一种类型转换到另一种类型。
这样可以省去很多的时间。
发表回复