这一篇文章也是写模型机的,但是为什么我会有两个?保险起见还是上传一下记录下来,免得我又把资料搞丢了。这一篇就不分成很多篇了。来个大的!

一、设计目的

系统掌握计算机的组成和工作原理,能够自助熟练准确地阐述计算机执行机器指令的工作过程,熟练应用并设计微指令、微程序的设计及调试。

二、设计内容

模型机与程序运行试验是一个综合性整机实验。该模型机包含7条机器指令,它能够依照用户执行微程序完成由加、与、非运算以及数据组合的任意复合运算。用户测试程序可以通过内存初始化的方式存储在内存中,也可以通过强迫写的方式循环写入内存。
这里我采用分模块整合法,此整机实验,由节拍脉冲、数据通路、微程序控制器、数码管显示4个模块组成。运算器、存储器、数据通路及微程序控制器中的时钟脉冲必须与时序电路相连。

1.以下为参考顶层电路:


2.设计指令表如下:


这个实验主要通过以下三个步骤完成:
首先,将各个元件进行设计,并生成相应的bsf文件,注意这里最好对每一个元件进行单独的仿真验证和测试,然后通过仿真结果进行检测,看看是否正常运行。这里每一个元件的源程序都可以在书上找到。
其次,将各个元件进行连接,先进行线路上的链接,将相同的信号进行连接,然后对整个电路进行仿真验证。这里的链接方法在书上都有,就是那个顶层实体图,然后时钟信号根据微体系结构图得到
最后,根据仿真验证的结果,对整个电路进行微调,主要是对时钟信号进行调整。

三、详细设计

3.1设计的整体架构

总共大大小小有13个元件,其中有书上所指示的,也有我自己设计的(如ir),通过这11个元件相互之间的配合和时序上的整合,实现7个机器指令的实现(由于我实现的比较早,所以我在犹豫要不要实现其他的机器指令,如sub)。其中有多种信号。

1、jiepai元件:

用来产生t1~t4时钟节拍脉冲的元件;如图所示:

LIBRARY ieee;
USE ieee.std_logic_1164.all;ENTITY jiepai ISPORT (clk : IN STD_LOGIC;tj : IN STD_LOGIC := '0';dp : IN STD_LOGIC := '0';qd : IN STD_LOGIC := '0';t1 : OUT STD_LOGIC;t2 : OUT STD_LOGIC;t3 : OUT STD_LOGIC;t4 : OUT STD_LOGIC;q1 : OUT STD_LOGIC;q2 : OUT STD_LOGIC;q3 : OUT STD_LOGIC);
END jiepai;ARCHITECTURE BEHAVIOR OF jiepai ISTYPE type_fstate IS (idle,st1,s_st2,st4,st2,st3,s_st4,s_st3);SIGNAL fstate : type_fstate;SIGNAL reg_fstate : type_fstate;SIGNAL reg_t1 : STD_LOGIC := '0';SIGNAL reg_t2 : STD_LOGIC := '0';SIGNAL reg_t3 : STD_LOGIC := '0';SIGNAL reg_t4 : STD_LOGIC := '0';
BEGINPROCESS (clk,reg_fstate)BEGINIF (clk='1' AND clk'event) THENfstate <= reg_fstate;END IF;END PROCESS;PROCESS (fstate,qd,dp,tj,reg_t1,reg_t2,reg_t3,reg_t4)BEGINreg_t1 <= '0';reg_t2 <= '0';reg_t3 <= '0';reg_t4 <= '0';t1 <= '0';t2 <= '0';t3 <= '0';t4 <= '0';CASE fstate ISWHEN idle =>IF (NOT((qd = '1'))) THENreg_fstate <= st1;ELSEreg_fstate <= idle;END IF;reg_t4 <= '0';reg_t3 <= '0';reg_t2 <= '0';reg_t1 <= '0';WHEN st1 =>IF (((tj = '1') AND NOT((dp = '1')))) THENreg_fstate <= st1;ELSIF (((dp = '1') AND NOT((tj = '1')))) THENreg_fstate <= s_st2;ELSEreg_fstate <= st2;END IF;reg_t4 <= '0';reg_t3 <= '0';reg_t2 <= '0';reg_t1 <= '1';WHEN s_st2 =>IF ((tj = '1')) THENreg_fstate <= s_st2;ELSEreg_fstate <= s_st3;END IF;reg_t4 <= '0';reg_t3 <= '0';reg_t2 <= '1';reg_t1 <= '0';WHEN st4 =>IF (((tj = '1') AND NOT((dp = '1')))) THENreg_fstate <= st4;ELSIF (((dp = '1') AND NOT((tj = '1')))) THENreg_fstate <= idle;ELSEreg_fstate <= st1;END IF;reg_t4 <= '1';reg_t3 <= '0';reg_t2 <= '0';reg_t1 <= '0';WHEN st2 =>IF (((tj = '1') AND NOT((dp = '1')))) THENreg_fstate <= st2;ELSIF (((dp = '1') AND NOT((tj = '1')))) THENreg_fstate <= s_st3;ELSEreg_fstate <= st3;END IF;reg_t4 <= '0';reg_t3 <= '0';reg_t2 <= '1';reg_t1 <= '0';WHEN st3 =>IF (((tj = '1') AND NOT((dp = '1')))) THENreg_fstate <= st3;ELSIF (((dp = '1') AND NOT((tj = '1')))) THENreg_fstate <= s_st4;ELSEreg_fstate <= st4;END IF;reg_t4 <= '0';reg_t3 <= '1';reg_t2 <= '0';reg_t1 <= '0';WHEN s_st4 =>IF ((tj = '1')) THENreg_fstate <= s_st4;ELSEreg_fstate <= idle;END IF;reg_t4 <= '1';reg_t3 <= '0';reg_t2 <= '0';reg_t1 <= '0';WHEN s_st3 =>IF ((tj = '1')) THENreg_fstate <= s_st3;ELSEreg_fstate <= s_st4;END IF;reg_t4 <= '0';reg_t3 <= '1';reg_t2 <= '0';reg_t1 <= '0';WHEN OTHERS => reg_t1 <= 'X';reg_t2 <= 'X';reg_t3 <= 'X';reg_t4 <= 'X';report "Reach undefined state";END CASE;t1 <= reg_t1;t2 <= reg_t2;t3 <= reg_t3;t4 <= reg_t4;END PROCESS;
END BEHAVIOR;

这是第五次实验——时序电路实验的内容,如果能够正确完整的完成第五次实验,那么这个就不是什么难题。第五次实验教会了我们一种使用quartus软件画状态图并生成vhdl的方法。这个元件主要是生成四个时钟脉冲信号,通过这四个时钟脉冲信号控制整个电路。

2、kongzhi元件:

整个控制器的元件,其中包含了rom(用来产生相应的微指令信号)元件和pp(我自己设置的,用来控制下址)元件;如图所示:

pp元件的vhdl为:

library ieee;
use ieee.std_logic_1164.all;
entity pp is
port(clock:in std_logic;p:in std_logic;ir7:in std_logic;ir6:in std_logic;ir5:in std_logic;a5:in std_logic;a4:in std_logic;a3:in std_logic;a2:in std_logic;a1:in std_logic;rd:in std_logic;we:in std_logic;o5:out std_logic;o4:out std_logic;o3:out std_logic;o2:out std_logic;o1:out std_logic);
end pp;
architecture rtl of pp is
signal aa,bb:std_logic;
begin
process(clock,p,ir7,ir6,ir5,rd,we)
beginif(rd='0') theno5<=a5;o4<=a4;o3<=a3;o2<=a2;o1<=a1;elsif(we='0') theno5<='1';o4<='0';o3<='0';o2<='0';o1<='0';elseif(p='0') theno5<=a5;o4<=a4;o3<=a3;o2<=a2;o1<=a1;elsif(ir7='0' and ir6='0' and ir5='0')theno5<=a5;o4<=a4;o3<=a3;o2<=a2;o1<=a1; elseo5<='0';o4<='1';o3<=ir7;o2<=ir6;o1<=ir5;end if;end if;
end process;
end rtl;

rom元件的vhdl为:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY rom IS
PORT
(a4,a3,a2,a1,a0:in std_logic;d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,d18,d19,d20,d21,d22,d23,d24,d25,d26,d27,d28:out std_logic           --address  : IN     STD_LOGIC_VECTOR (4 DOWNTO 0);          --          q  : OUT STD_LOGIC_VECTOR (27 DOWNTO 0)
);
END rom;
ARCHITECTURE SYN OF rom IS
signal address:std_logic_vector(4 downto 0);
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (27 DOWNTO 0);
BEGIN
address<=a4&a3&a2&a1&a0;
sub_wire0<=
"1010111100000001000000000001"     WHEN address=     "00000"   ELSE
"1111111000001001000000000010"     WHEN address=     "00001"   ELSE
"1001111100000101000001001000"     WHEN address=     "00010"   ELSE
"1001111100000001000000110011"     WHEN address=     "01000"   ELSE
"1111111000001001000000010101"     WHEN address=     "01001"   ELSE
"1111111000001001000000010111"     WHEN address=     "01010"   ELSE
"1111111000001001000000011001"     WHEN address=     "01011"   ELSE
"1001101100010001000000011011"     WHEN address=     "01100"   ELSE
"1111111000001001000000011100"     WHEN address=     "01101"   ELSE
"1111111000001001000000000011"     WHEN address=     "01110"   ELSE
"1111111000001001000000011101"     WHEN address=     "01111"   ELSE
"1001111100001001000001010110"     WHEN address=     "10101"   ELSE
"1001111110000001000001000001"     WHEN address=     "10110"   ELSE
"1001111100001001000001011000"     WHEN address=     "10111"   ELSE
"1001101100000001000010000001"     WHEN address=     "11000"   ELSE
"1001111100001001000001011010"     WHEN address=     "11001"   ELSE
"1000111100000001000001000001"     WHEN address=     "11010"   ELSE
"1001110110000010000000000001"     WHEN address=     "11011"   ELSE
"1011111100000001000001000001"     WHEN address=     "11100"   ELSE
"1001111100001001000001000100"     WHEN address=     "00011"   ELSE
"1001111100100001000001000101"     WHEN address=     "00100"   ELSE
"1001101100010001000000000110"     WHEN address=     "00101"   ELSE
"1001110110000001100100000001"     WHEN address=     "00110"   ELSE
"1001111100001001000001011110"     WHEN address=     "11101"   ELSE
"1001111100100001000001011111"     WHEN address=     "11110"   ELSE
"1001101100010001000000000111"     WHEN address=     "11111"   ELSE
"1001110110000000101100000001"     WHEN address=     "00111"   ELSE
"1010111100000001000000010001"     WHEN address=     "10000"   ELSE
"1111111000001001000000010010"     WHEN address=     "10001"   ELSE
"1111111000001001000000010100"     WHEN address=     "10011"   ELSE
"1000111100000001000010010001"     WHEN address=     "10010"   ELSE
"1001111100000001000001010011"    ;
d1<=sub_wire0(27);
d2<=sub_wire0(26);
d3<=sub_wire0(25);
d4<=sub_wire0(24);
d5<=sub_wire0(23);
d6<=sub_wire0(22);
d7<=sub_wire0(21);
d8<=sub_wire0(20);
d9<=sub_wire0(19);
d10<=sub_wire0(18);
d11<=sub_wire0(17);
d12<=sub_wire0(16);
d13<=sub_wire0(15);
d14<=sub_wire0(14);
d15<=sub_wire0(13);
d16<=sub_wire0(12);
d17<=sub_wire0(11);
d18<=sub_wire0(10);
d19<=sub_wire0(9);
d20<=sub_wire0(8);
d21<=sub_wire0(7);
d22<=sub_wire0(6);
d23<=sub_wire0(5);
d24<=sub_wire0(4);
d25<=sub_wire0(3);
d26<=sub_wire0(2);
d27<=sub_wire0(1);
d28<=sub_wire0(0);
END SYN;

这是第六次实验的内容,主要在于rom元件的设计和信号的安排。可以直接拿来用。

3、shutong元件

数据通路元件,其中包含了exp_r_alu(alu运算器模块,用来进行数据运算)元件和exp_ram_vhd(其中包含了ram寄存器模块和pc、ar寄存器模块,用来访问内存文件,产生指令,产生计数,存储指令和地址)元件;

exp_r_alu元件的vhdl为:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity exp_r_alu is
port( clk1:in std_logic;--t3clk2:in std_logic;--t2sw_bus,r4_bus,r5_bus,alu_bus:in std_logic;lddr1,lddr2,ldr4,ldr5:in std_logic;m,cn:in std_logic;s:in std_logic_vector(3 downto 0);k:in std_logic_vector(7 downto 0):="00000000";d:inout std_logic_vector(7 downto 0);--ou:out std_logic_vector(7 downto 0);rr5:out std_logic_vector(7 downto 0);rr4:out std_logic_vector(7 downto 0);rr1:out std_logic_vector(7 downto 0);rr2:out std_logic_vector(7 downto 0));
end exp_r_alu;
architecture rtl of exp_r_alu is
signal dr1,dr2,r4,r5,aluout,bus_reg:std_logic_vector(7 downto 0);
signal sel:std_logic_vector(5 downto 0);
begin
ldreg:process(clk1,clk2,lddr1,lddr2,ldr4,ldr5,bus_reg)beginif clk1'event and clk1='1' thenif ldr4='1' then r4<=bus_reg;elsif ldr5='1' then r5<=bus_reg;end if;end if;if clk2'event and clk2='1' thenif lddr1='1' then dr1<=bus_reg;elsif lddr2='1' then dr2<=bus_reg;end if;end if;end process;
alu:process(m,cn,s,dr1,dr2,sel,aluout)beginsel<=m&cn&s;case sel iswhen "000000"=>aluout<=dr1+1;when "010000"=>aluout<=dr1;when "100000"=>aluout<=not dr1;when "000001"=>aluout<=(dr1 or dr2)+1;when "010001"=>aluout<=dr1 or dr2;when "100001"=>aluout<=not(dr1 or dr2);when "000010"=>aluout<=(dr1 or (not dr2))+1;when "010010"=>aluout<=(dr1 or (not dr2));when "100010"=>aluout<=(not dr1)and dr2;when "000011"=>aluout<=x"00";when "010011"=>aluout<=aluout-1;when "100011"=>aluout<=x"00";when "000100"=>aluout<=dr1+(dr1 and (not dr2))+1;when "010100"=>aluout<=dr1+(dr1 and (not dr2));when "100100"=>aluout<=not(dr1 and dr2);when "000101"=>aluout<=(dr1 or dr2)or(dr1 and dr2)or x"01";when "010101"=>aluout<=(dr1 or dr2)+(dr1 and (not dr2));when "100101"=>aluout<=not dr2;when "000110"=>aluout<=dr1-dr2;when "010110"=>aluout<=dr1-dr2-1;when "100110"=>aluout<=dr1 xor dr2;when "000111"=>aluout<=dr1 and (not dr2);when "010111"=>aluout<=(dr1 and (not dr2))-1;when "100111"=>aluout<=dr1 and(not dr2); when "001000" => aluout<=dr1 + (dr1 and dr2)+1;when "011000" => aluout<=dr1 + (dr1 and dr2);when "101000" => aluout<= (not dr1) or dr2;when "001001" => aluout<=dr1 + dr2 +1;when "011001" => aluout<=dr1 + dr2;when "101001" => aluout<=(dr1 xnor dr2);when "001010" => aluout<=(dr1 or(not dr2))+(dr1 and dr2)+1;when "011010" => aluout<=(dr1 or(not dr2))+(dr1 and dr2);when "101010" => aluout<=dr2;when "001011" => aluout<=dr1 and dr2;when "011011" => aluout<=(dr1 and dr2)-1;when "101011" => aluout<=(dr1 and dr2);when "001100" => aluout<=dr1 + dr1 +1;when "011100" => aluout<=(dr1 or dr1); when "101100" => aluout<=x"01";when "001101" => aluout<=(dr1 or dr2)+dr1+1;when "011101" => aluout<=(dr1 or dr2)+dr1;when "101101" => aluout<=dr1 or(not dr2);when "001110" => aluout<=(dr1 or (not dr2))+dr1+1;when "011110" => aluout<=(dr1 or (not dr2))+dr1;when "101110" => aluout<=dr1 or dr2;when "001111" => aluout<=dr1;when "011111" => aluout<=dr1-1;when "101111" => aluout<=dr1;when others =>aluout<=x"ff";end case;end process;bus_Reg<=k      when(sw_bus='0' and r4_bus='1' and r5_bus='1' and ALU_bus='1') elser4      when(sw_bus='1' and r4_bus='0' and r5_bus='1' and ALU_bus='1') elser5      when(sw_bus='1' and r4_bus='1' and r5_bus='0' and ALU_bus='1') elsealuout  when(sw_bus='1' and r4_bus='1' and r5_bus='1' and ALU_bus='0') else d;d<=bus_Reg when(sw_bus='0' or r4_bus='0' or r5_bus='0' or ALU_bus='0') else--******(others=>'Z');rr5<=r5;rr4<=r4;rr1<=dr1;rr2<=dr2;
end rtl;

exp_ram_vhd元件为:

其中的sw_pc_ar元件的vhdl为:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity sw_pc_ar is
port(clk_cdu,pcclr,pcld,pcen:in std_logic;--Z,1,0,0sw_bus,pc_bus,ldar:in std_logic;--1,1,0inputd:in std_logic_vector(7 downto 0):="00000000";arout:out std_logic_vector(7 downto 0);d:inout std_logic_vector(7 downto 0);pco:out std_logic_vector(7 downto 0));
end sw_pc_ar;
architecture rtl of sw_pc_ar is
signal pc,ar,bus_reg:std_logic_vector(7 downto 0):="00000000";
begin
seql:process(clk_cdu,ldar,bus_reg)--when ldar==1 let bus into arbeginif clk_cdu'event and clk_cdu='1' thenif ldar='1' thenar<=bus_reg;end if;end if;end process;
sep2:process(clk_cdu,pcclr,pcld,pcen,bus_reg)beginif pcclr='0' then--when pcclr==0 clear pcpc<=(others=>'0');elsif clk_cdu'event and clk_cdu='1' thenif (pcld='0' and pcen='1') then--when pcen==1 & pcld==0 let bue into pcpc<=bus_reg;elsif (pcld='1' and pcen='1') then--when pcen==1 & pcld==1 pc++pc<=pc+1;end if;end if;end process;
bus_reg<=inputd when (sw_bus='0' and pc_bus='1') else--when pc_bus==1 let inputd in buspc when (sw_bus='1' and pc_bus='0') else--when sw_bus==1 let pc in busd;--when 0 0 let d in bus
d<=bus_reg when (sw_bus='0' or pc_bus='0') else--when 0 0 let bus into d(others=>'Z');--when else let Z into d
arout<=ar;--show ar
pco<=pc;
end rtl;

这是第四次实验的内容,已经将总线和alu进行了整合,十分的简单和方便。如果能够完整的完成第四次实验的仿真和下载,那么并不是什么难事。

4、xianshi元件:

显示模块并不是实验中要求的,而更多的是我们自己学习的,是附加电路的内容,由于附加电路是我自己完全独立设计的,没有参考书上的什么内容,所以我比较熟悉,也比较清楚它的各个端口是做什么的,有什么样的作用,再加上我曾经做的跑马灯,对于八个数码管的同时显示也比较熟悉,所以总的来说,设计出来并不是太难。
显示数码管元件,其中包含了seg(用来控制段选信号的模块)元件、cpu16(用来产生计数的模块)元件和sanba(用来控制位选信号的模块)元件,下文会进行详细的介绍。
在所有的信号中,clk是执行模块(包括控制器和数据通路)的时钟输入信号,clock是显示模块的时钟输入信号,clr、krd、kwe是控制器的控制输入信号,tj、dp、qd是节拍(时序电路)的控制输入信号,k是数据输入信号,其他所有的信号均为输出信号,用来检测是否运行正确以及下载后控制数码管显示数据。注意寄存器的初值已经在编写的时候输入到了寄存器的mif文件中,在后续的演示中除了想要增加,不需要人为输入。
在检测的时候主要观察ir7~ir6信号(指令信号),p信号(总使能信号),rr5信号(r5寄存器数据输出信号),pc信号(计数器数据输出信号),bus信号(总线数据输出信号),ao信号(ar寄存器数据输出信号)。
运行的时候以每4个时钟脉冲周期为一个微指令周期,多个微指令周期为一个机器指令周期,实现一个机器指令。
在这里,我是严格按照书上的要求设计的时钟信号,只是在显示模块的时候加入了一个新的时钟信号,用来控制持续显示而不是频闪。

3.2附加电路说明

1、seg模块:

用来产生段选信号的,通过输入的数据来产生相应的段选信号,用来控制在数码管上的显示来输出数据,vhdl如下:

library ieee;
use ieee.std_logic_1164.all;
entity seg is
port(input:in std_logic_vector(3 downto 0);en:in std_logic;output:out std_logic_vector(7 downto 0));
end seg;
architecture ru of seg is
begin
process(input,en)
begin
if en='1' then   if input="0000" thenoutput<="11111100";elsif input="0001" thenoutput<="01100000";elsif input="0010" thenoutput<="11011010";elsif input="0011" thenoutput<="11110010";elsif input="0100" thenoutput<="01100110";elsif input="0101" thenoutput<="10110110";elsif input="0110" thenoutput<="10111110";elsif input="0111" thenoutput<="11100000";elsif input="1000" thenoutput<="11111110";elsif input="1001" thenoutput<="11110110";elsif input="1010" thenoutput<="11101110";elsif input="1011" thenoutput<="00111110";elsif input="1100" thenoutput<="10011100";elsif input="1101" thenoutput<="01111010";elsif input="1110" thenoutput<="10011110";elsif input="1111" thenoutput<="10001110";   end if;
else output<="00000010";
end if;
end process;
end ru;

当en为1的时候可以输出数据相应的段选信号,当en为0的时候将会输出一条杠

2、cpu16元件:

用来产生计数的,用来控制哪个数码管在哪个时候进行显示,具体代码如下:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY cpu16 IS
PORT(CLK,RST,EN : IN STD_LOGIC;CQ : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);COUT : OUT STD_LOGIC);
END ENTITY cpu16;
ARCHITECTURE behav OF cpu16 IS
BEGIN
PROCESS (CLK,RST,EN)VARIABLE CQI : STD_LOGIC_VECTOR(3 DOWNTO 0);BEGINIF RST='1' THEN CQI:=(OTHERS =>'0');ELSIF CLK'EVENT AND CLK='1' THENIF EN='1' THEN IF CQI<7 THEN CQI:=CQI+1;ELSE CQI := (OTHERS =>'0');END IF;END IF;END IF;IF CQI=2 THEN COUT<='0';elsif cqi=5 then cout<='0';ELSE COUT<='1';END IF;CQ<=CQI;
END PROCESS;
END ARCHITECTURE behav;

将会进行0~7的数字循环,每个数字对应一个数码管,实际上就是一个简单的数字计数器罢了。

3、sanba译码器元件:

用来产生位选信号,用来配合cput16控制哪个数码管在哪个时间进行显示,vhdl如下:

library ieee;
use ieee.std_logic_1164.all;
entity sanba is
port(input:in std_logic_vector(2 downto 0);o0:out std_logic;o1:out std_logic;o2:out std_logic;o3:out std_logic;o4:out std_logic;o5:out std_logic;o6:out std_logic;o7:out std_logic);
end sanba;
architecture ru of sanba is
signal output:std_logic_vector(7 downto 0);
begin
process(input)
begin
if input="000" thenoutput<="00000001";
elsif input="001" thenoutput<="00000010";
elsif input="010" thenoutput<="00000100";
elsif input="011" thenoutput<="00001000";
elsif input="100" thenoutput<="00010000";
elsif input="101" thenoutput<="00100000";
elsif input="110" thenoutput<="01000000";
elsif input="111" thenoutput<="10000000";
end if;
end process;
o0<=not output(7);
o1<=not output(6);
o2<=not output(5);
o3<=not output(4);
o4<=not output(3);
o5<=not output(2);
o6<=not output(1);
o7<=not output(0);
end ru;

将会循环使8位数码管进行显示

3.3仿真结果说明



具体分析如下:
115ns~285ns执行的是LDA指令,将03H给r5寄存器
先进行01001指令,将pc中的数值给ar寄存器,pc再加1,此时ar的值为01H
再进行10101指令,将ram中ar位置的地址的数值取出来,再给ar寄存器,此时ram取出来的数值是14H,ar寄存器的数值即为14H
再进行10110指令,将ram中ar位置的地址的数值取出来,再给r5寄存器,此时ram取出来的数值是03H ,r5寄存器的数值即为03H
285ns~475ns执行的是COM指令,将03H取反得到FCH再赋值给r5寄存器
先进行01100指令,将r5寄存器的数值放到dr1暂存器中,此时dr1暂存器的数值为03H
再进行11011指令,将dr1中的数值进行取反操作后再赋值给r5寄存器,此时r5寄存器的数值为FCH
475ns~795ns执行的是ADD指令,相加后结果为FDH在赋值给r5寄存器
先进行01110指令,将pc中的数值给ar寄存器,pc再加1,此时ar的值为04H
再进行00011指令,将ram中ar位置的地址的数值取出来,再给ar寄存器,此时ran取出来的数值是12H,ar寄存器的数值即为12H
再进行00100指令,将ram中ar位置的地址的数值取出来,再给dr2暂存器,此时ram取出来的数值是01H,dr2寄存器的数值即为01H
再进行00101指令,将r5寄存器的数值给dr1暂存器,此时dr1暂存器的数值为FCH
再进行00110指令,将dr1和dr2的数值进行相加,再将结果给r5寄存器,此时r5寄存器的数值为FDH
795ns~1045ns执行的是STA指令,将r5寄存器中的值放到ram中
先进行01010指令,将pc中的数值给ar寄存器,pc再加1,此时ar的数值为06H
再进行10111指令,将ram中ar位置的地址的数值取出来,再给ar寄存器,此时ram取出来的数值是16H,ar寄存器的数值即为16H
再进行11000指令,将r5寄存器的数值放到ram中ar位置的地址
1045ns~1275ns执行的是LDA指令,将02H给r5寄存器
先进行01001指令,将pc中的数值给ar寄存器,pc再加1,此时ar的值为08H
再进行10101指令,将ram中ar位置的地址的数值取出来,再给ar寄存器,此时ram取出来的数值是13H,ar寄存器的数值即为02H
再进行10110指令,将ram中ar位置的地址的数值取出来,再给r5寄存器,此时ram取出来的数值是02H,r5寄存器的数值即为02H
1275ns~1595ns执行的是ADD指令,相加后结果为06H再赋值给r5寄存器
先进行01110指令,将pc中的数值给ar寄存器,pc再加1,此时ar的值为0AH
再进行00011指令,将ram中ar位置的地址的数值取出来,再给ar寄存器,此时ran取出来的数值是15H,ar寄存器的数值即为15H
再进行00100指令,将ram中ar位置的地址的数值取出来,再给dr2暂存器,此时ram取出来的数值是04H,dr2寄存器的数值即为04H
再进行00101指令,将r5寄存器的数值给dr1暂存器,此时dr1暂存器的数值为02H
再进行00110指令,将dr1和dr2的数值进行相加,再将结果给r5寄存器,此时r5寄存器的数值为06H
1595ns~1915ns执行的是AND指令,相与后结果为04H再赋值给r5寄存器
先进行01110指令,将pc中的数值给ar寄存器,pc再加1,此时ar的值为0CH
再进行11101指令,将ram中ar位置的地址的数值取出来,再给ar寄存器,此时ram取出来的数值是16H,ar寄存器的数值即为16H
再进行11110指令,将ram中ar位置的地址的数值取出来,再给dr2暂存器,此时ram取出来的数值是FDH,dr2暂存器的数值即为FDH
再进行11111指令,将r5寄存器的数值给dr1暂存器,此时dr1暂存器的数值即为06H
再进行00111指令,将dr1和dr2的数值进行相与,再将结果给r5寄存器,此时r5寄存器的数值为04H
1915ns~2115ns执行的是COM指令,将04H取反得到FBH再赋值给r5寄存器
先进行01100指令,将r5寄存器的数值放到dr1暂存器中,此时dr1暂存器的数值为04H
再进行11011指令,将dr1中的数值进行取反操作后再赋值给r5寄存器,此时r5寄存器的数值为FBH
2115ns~2365ns执行的是OUT指令,将存储器16H位置的值展示到bus上
先进行01011指令,将pc中的数值给ar寄存器,pc再加1,此时ar的数值为0FH
再进行11001指令,将ram中ar位置的地址的数值取出来,再给ar寄存器,此时ram取出来的数值是16H
再进行11010指令,将ram中ar位置的地址的数值取出来,再发送到总线,此时总线上的数值为FDH
2365ns~2565ns执行的是JMP指令,跳转回00H位置的指令重复执行
先进行01101指令,将pc中的数值给ar寄存器,pc再加1,此时ar的值为11H
再进行11100指令,将ram中ar位置的地址的数值取出来,再给pc计数器,此时ram取出来的数值是00H,pc计数器的数值即为00H

3.4mif文件展示

3.5报告

1)假如控制器中模拟指令码的ir7ir6ir5对应到数据总线d[7…0]的d4d6d1,译码出7条机器指令的指令码为:

机器指令 指令码 二进制指令码 十六进制指令码
LDA 001 00000001 01H
STA 010 01000000 40H
ADD 110 01010000 50H
AND 111 01010001 51H
COM 100 00010000 10H
OUT 011 01000001 41H
JMP 101 00010001 11H

2)用模型机已有的7条机器指令编写测试程序,实现复合运算:

not((not(c))加a)and(b加d))
其中a=01H,b=02H,c=03H,d=04H
先将数据c放入r5寄存器中,再进行not(c),将结果放在r5寄存器中,
再进行not(c)加a,将结果放在r5寄存器中,将结果放到存储器中,
再将数据b放入r5寄存器中,再进行(b加d),结果放到r5寄存器中,
再将存储器中存储的not(c)加a取出,与r5进行相与,将结果放到r5寄存器中,
再对r5寄存器进行取反操作,结果放到r5寄存器中,
此时r5寄存器中的值就是我们要进行的复合运算的最终值

具体的代码表如下:

RAM地址 内容 说明
00H 20H LDA双字节指令
01H 14H LDA 14将地址14H中内容送到r5(r5=03H)
02H 80H COM单字节指令,将r5取反送到r5(r5=FCH)
03H C0H ADD双字节指令
04H 12H ADD 12将地址12H中的内容与r5相加送到r5(r5=FDH)
05H 40H STA双字节指令
06H 16H STA 16将r5的值放到地址16H的单元
07H 20H LDA双字节指令
08H 13H LDA 13将地址13H中内容送到r5(r5=02H)
09H C0H ADD双字节指令
0AH 15H ADD 15将地址15H中的内容与r5相加送到r5(r5=06H)
0BH E0H AND双字节指令
0CH 16H AND 16将地址16H中的内容与r5相与送到r5(r5=04H)
0DH 80H COM单字节指令,将r5取反送到r5(r5=FBH)
0EH 60H OUT双字节指令
0FH 16H OUT 16将地址16H中的内容送到BUS
10H A0H JMP双字节指令
11H 00H JMP 00无条件转移到00H地址
12H 01H 数据a
13H 02H 数据b
14H 03H 数据c
15H 04H 数据d
16H 00H 数据暂存

a,b,c,d的值存储在12H~15H的位置
mif文件为:

下载图示:

1、针脚设置:


芯片还是选取ep5t144c8的芯片,因为我们的芯片就是这个,仅支持这个
将qd模型机启动控制信号,clr清零控制信号,kwe强读控制信号和krd强写控制信号放在了按钮开关,因为他们的初始值是1;
将k八位输入数据,tj停机信号,dp单拍进行控制信号放在了拨码开关,因为他们的初始值是0,而且这样可以方便我进行数值设置。
通过数码管显示ar寄存器,bus总线和r5寄存器的数值。
通过二极管101-104来显示t1-t4四个节拍脉冲信号。二极管93,92,87分别代表ir7,ir6,ir5,为ir寄存器输出的数值。
给模型机的时钟信号是91时钟信号,频率为100hz,便于观测;
给显示数码管的时钟信号是17时钟信号,以此来消除频闪。
针脚设计好之后点击全编译,生成sof文件。
通过programer工具将sof文件加在到板子上。

2、下载结果:
指令 图示(由左到右依次是ar-bus-r5)
初始状态
LDA转移指令,r5=03H
COM取反指令,r5=FCH
ADD相加指令,r5=FDH
STA存储指令,bus=FDH
LDA转移指令,r5=02H
ADD相加指令。r5=06H
AND相与指令,r5=04H
COM取反指令,r5=FBH
OUT输出指令,bus=00H
JMP跳转指令,ar=00H

由此可以看出,在JMP指令执行后,r5寄存器中的值就是我们所要的复合运算的值FB。

3)回答问题

a、代码中进程ct1、ct2、ct3、ct4功能划分的依据是
ct1的功能是微序列控制器下址跳转
ct2的功能是实现各种指令,主要集中在实现从存储器或寄存器释放数据到总线上
ct3的功能是完成各种指令,从总线上装载数据到相应的存储器或寄存器中
ct4的功能是生成下址

b、代码中如何定义并初始化RAM
通过定义一个名叫ram8的中间变量进行定义,并通过赋初值来进行初始化:
signalram8: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”)
其中括号中的数据是放入的初始值,即原本mif文件中的数据

c、代码中bus_reg_t2<=ram8(conv_integer(ar))与ram8(conv_integer(ar))<=r5的含义是什么
第一句是将ram中ar地址位置的数据值传送到总线上
第二句是将r5寄存器中的数据值传送到ram中ar地址的位置

4)vhdl中如何考虑多个时钟信号的情况

由于vhdl中是通过process进程进行设计的,所以只需要在进程中对不同的时钟信号进行条件选择,就可以在不同的时钟信号执行不同的操作。
但是注意要考虑到时序上的整合问题。
比方说,本次试验的时候,可以有四个不同的时钟信号,但是一定要满足:
在最先到达的一个时钟的波峰进行微序列控制器的下址跳转;
在第二个到达的波峰进行取数据的功能,即将数据从寄存器或存储器中取出来放到总线上,例如从ram中取出运算数据发送到总线上;
在第三个到达的波峰进行存数据的功能,即将数据从总线上存到寄存器或存储器中,例如将总线上的运算结果存回到r5寄存器中;
在最后一个到达的波峰进行下一个下址的生成。
虽然我是通过bdf和bsf的元件拼接整合实现的,但在我的整合过程中也注意了时序上的整合问题,比方说我给当前下址寄存器的时钟信号是t2时序脉冲,给寄存器和存储器的时钟信号一般是t3时序脉冲,给pp(我自己设计的下一下址寄存器)元件的时钟信号是t4时序脉冲,通过这样才达到了整个电路的正常运行。
当然,时序上的整合顺序不只有这一种,可以通过不同的设计方式进行,比方说我的舍友就将p1信号进行了提前,这样他就会提前进行判断是否进行强读强写,然后他又将所有的时钟信号进行了一个延迟,也做到了模拟机的正常运行。
所以我认为,时序上的整合方式不只有一种,我是按照书上的整合方式来的,并没有做太多的改动,但我也不认为只有我这种是正确的,毕竟这是一个开放性的大综合实验,只要能够设计出来,能够正常运行,就是可以的。

四、优化

因为我们可以有多个输出,想要查看多个值,如r5寄存器,r1暂存器,r2暂存器,pc计数器,ar寄存器,bus总线等等,而我们的数码管只有八个,只能显示3组数据,所以有些不够用,而我在我的搭档俞阳博的启发下,想到了一种可以多个显示的方法,即通过拨码开关来控制显示哪个数据,哪个寄存器,如下:
我定义了拨码开关52和51两个输入来控制r5,r1,r2,pc显示哪一个寄存器或计数器的数值,当52~51=00的时候(初始状态),第三组数码管显示r5寄存器的数值;当=01的时候显示r1暂存器的数值;当=10的时候显示r2暂存器的数值;当=11的时候显示pc计数器的数值。具体代码如下:

library ieee;
use ieee.std_logic_1164.all;
entity tf is
port(kg:in std_logic_vector(1 downto 0);m1:in std_logic_vector(7 downto 0);m2:in std_logic_vector(7 downto 0);m3:in std_logic_vector(7 downto 0);m4:in std_logic_vector(7 downto 0);mo:out std_logic_vector(7 downto 0));
end tf;
architecture rtl of tf is
begin
cin:process(kg)
beginif kg="00" thenmo<=m1;elsif kg="01" thenmo<=m2;elsif kg="10" thenmo<=m3;elsemo<=m4;end if;
end process;
end rtl;

实际上只不过是一个二四译码器的变形,根据输入的kg控制信号,来选择输出哪个八位的二进制数据,然后将输出的八位的二进制数据连接到显示模块的第三个输入数据,就可以通过52~51拨码开关进行控制要输出什么数据。
下载结果如下:

拨码开关(52~51) 数码管(ar-bus-r5/r1/r2/pc)
00(r5)
01(r1)
10(r2)
11(pc)

由此可以看出,当ar=03,bus=04,r5=FC的时候,执行的应该是COM取反指令,此时的r1暂存器的值是03(保持上一指令的数据,并没有用到),r2暂存器的值是00(并没有用到),pc计数器的值是04(即将执行下一指令)。结果正确。
由此可以看出,这么设置之后整个实验的观测简单了很多,也方便了很多,在这里特别感谢我的搭档俞阳博提出的这么一个想法,我之前自己并没有想到。

五、总结

作为计算机系统原理实验第一部分的最后一个大综合实验,本次实验难度系数高,实验复杂,涉及了开学五个周以来所学习的所有的知识点,而且不仅仅是简单的数据规模以及模块元件上的整合,更重要的是时钟脉冲信号上的整合,通过对t1~t4这四个时钟节拍的合理调用,来调度整个电路的正常进行。
总的来说,在昨晚之前的六个实验之后,模拟机各个组件的实现已经不再是十分困难的存在了,困难的是如何将所有的原件进行组织上和时序上的整合,一旦有什么不对,结果就很容易出差错。我基本上是通过书上的大部分内容进行设计的,在最后加上了少部分自己的一些元件用来确保整个电路的正常进行。
模拟机这个实验设计是我从第四周周二就开始了,一直写了差不多一个周才算基本完成,后来因为强读和强写操作并不是很容易写出来,所以又进行了大量的修改,最终是在第五周的周四全部实现了。
实际上,这次我感觉还是比较简单的,和上学期写CPU时我写了六个CPU才得到一个我比较满意的版本相比,我这次总共就写了两个就基本上实现了,因为做模拟机有书进行对照,所以并不是十分困难。但是不可否认,这次大综合实验非常的繁琐,虽然有了书的指导之后,不再像上学期那样全靠自己摸索,而是终于有迹可循,不过书上的内容也不能全信,我的第一个版本就是因为完全按照书上的指导来进行,所以失败了。这第二个版本我增加了很多我自己的东西,虽然和书上的内容已经不完全一样了,但可以按照我的想法实现指令,而且我个人感觉更加的简单易懂,通俗高效,所以如果说通过这次实验让我明白了什么的话,最大的感触就是必能完全按照书上的指导来进行实验,既然是实验,那么必须要有自己原创的部分,而且,也只有经过自己原创来实现的实验,来完成的功能,才能说明自己已经完完全全的掌握了这个实验怎么进行,怎么操作,还有以后如果想要更改的话,怎么在现有的基础上进行优化和删改。
截止到3月28日晚1点,我设计出来的模拟机已经经过了22次大改,34次功能仿真,14次下载验证,其他大大小小的改动不计其数,最终得到的版本已经是我觉得我能达到的巅峰状态了,可以很完美的实现所要求的全部七条指令,可以在01000地址进行判断的时候执行强读RAM和强写RAM的操作,可以说在我能够想到的所有的测试情况中已经没有任何的bug了,我也觉得仅凭我自己已经没有办法再做什么大型的优化了。

六、以下是我的实验日志:

时间:3月19日
地点:工训中心
内容:主要还是完成控制器,对于控制器的rom的设计还是感觉没有底气,总感觉有些rom的指令有问题,但不知道哪里有问题,将微程序控制器进行连线,看了一下模拟机的指导,感觉前途灰暗。。。

时间:3月20日
地点:305宿舍
内容:和舍友冯昂的rom的信号设计进行和相互的比较,讨论之后感觉收获很大,修改了很多,但是微程序控制器的时钟信号感觉出现了一些问题,还需要进行修改
晚上12点,已经完成了微程序控制器的修改,仿真的结果感觉也没有问题,接下来就剩下载验证了

时间:3月21日
地点:工训中心&305宿舍
内容:完成了微程序控制器的下载验证,感觉没有问题,可以单拍运行也可以持续运行,但感觉并不是太懂如何操作,还是需要再熟悉一下。模拟机正式开始,将各个元件进行了创立,并在工程中进行了连接,但感觉并没有什么头绪,肯定不能简单的进行连接,还需要进一步地阅读资料才行

时间:3月23日
地点:工管院
内容:完成了模拟机的第一个版本,但感觉。。。怎么说呢。。。很乱,信号乱七八糟,而且大部分都是一堆的叉号,不能用,绝对有问题,还是不能完全按照树上的来,书上的很多元件的很多端口之前设计的实验中都没有,不能完全按照书上来,这个应该就是废掉了,还需要一个新的版本进行设计。

时间:3月25日
地点:工训中心
内容:完成了模拟机的训练题(训练七),感觉懂了很多,之前一直不明白为什么会有四个时钟周期,也不懂为什么会有那么多的信号(28个,真的搞人),还是需要再看一下书,感觉书上的另外几个图还是有些用的,比方说那个时序的图

时间:3月27日
地点:305宿舍
内容:将第二个版本初步连接出来了,感觉还不错,图形上没有问题,但时序上的整合还是需要设计

时间:3月28日
地点:工训中心&305宿舍
内容:第二个版本的电路整合已经没有问题了,对于时序的设计感觉也没有问题了,但一直有一个死循环,而且不是一直死循环,是前两个指令运行正常,在一个010指令运行的时候就读不进去,而且ir寄存器的输入,控制信号都引出来进行查看了,也没有问题,不知道到底为什么
晚上8点30分,总算查出来了,错了一个字母。。。
没有问题了,只是还是需要对强读强写信号进行一下设计,感觉虽然可以进入强读和强写的循环,但是没有办法对pc进行一个写的操作,还是需要更正和优化。
晚上10点20分,完成了强读信号和强写信号的优化,感觉已经没有什么明显的bug了,至少我已经找不出来了,开始写实验报告好了。
晚上11点30分,完成了实验报告的初稿

计算机系统实验:模型机(十六)另一篇?相关推荐

  1. [Python从零到壹] 三十六.图像处理基础篇之图像算术与逻辑运算详解

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  2. C/C++基础讲解(八十六)之游戏篇(解救人质游戏)

    C/C++基础讲解(八十六)之游戏篇(解救人质游戏) 程序之美 前言 很多时候,特别是刚步入大学的学子们,对于刚刚开展的计算机课程基本上是一团迷雾,想要弄明白其中的奥秘,真的要花费一些功夫,我和大家一 ...

  3. ArcGIS 实验理论基础二十六 中国人口密度图的制作

    实验27 中国人口密度图的制作 实验目的 了解专题地图的组成要素 掌握专题电子地图的制作方法 实验内容 制作中国人口密度电子地图 实验原理 专题地图突出反映一种或几种主体要素或现象 专题地图由图形要素 ...

  4. 山东大学软件学院项目实训-创新实训-网络安全靶场实验平台(十六)

    目录 一.什么是目录遍历漏洞? 二.后端实现 三.前端代码 四.效果图 前言:本篇博客主要记录目录遍历漏洞的实现. 一.什么是目录遍历漏洞? 目录遍历(也称为文件路径遍历)是一个Web安全漏洞,它使攻 ...

  5. 内网渗透(四十六)之横向移动篇-使用系统漏洞ms17010横向移动

    系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内 ...

  6. 【.NET Core项目实战-统一认证平台】第十六章 网关篇-Ocelot集成RPC服务

    一.什么是RPC RPC是"远程调用(Remote Procedure Call)"的一个名称的缩写,并不是任何规范化的协议,也不是大众都认知的协议标准,我们更多时候使用时都是创建 ...

  7. K8S 快速入门(十六)实战篇:StorageClass(存储类)

    StorageClass 存储类 官方文档 上一节演示了 PVC的自动化实现方式:利用volumeClaimTemplates 这一节将讲解PV的自动化: 利用StorageClass实现,可以根据P ...

  8. 基本模型机的设计与实现

    一.实验目的 在掌握部件单元电路的实验的基础上,构造一台基本模型计算机. 为其定义五条机器指令,并编写相应的微程序,上机调试掌握整机概念 二.实验设备 Dais-CMX16+ 计算机组成原理教学实验系 ...

  9. [Python从零到壹] 五十六.图像增强及运算篇之图像平滑(中值滤波、双边滤波)

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  10. [Python从零到壹] 三十九.图像处理基础篇之图像几何变换(镜像仿射透视)

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

最新文章

  1. 病毒周报(071029至071104)
  2. 算法------数组---------存在重复元素
  3. golang变量作用域
  4. 数学告诉你家庭关系的奥秘
  5. Github:视觉问答最新资源汇总
  6. php form 后台函数,Discuz!开发之后台表单生成函数介绍
  7. axios请求跨域前端解决_Vue-创建axios实例并实现跨域请求(完整过程-前端)
  8. C++类的构造函数、析构函数与赋值函数
  9. 计算机哪个专业学linux_5种用于计算机维修的专业Linux发行版
  10. android 车牌输入键盘
  11. 计算机程序停止工作怎么办,如何将“某某程序已正常停止工作,请关闭程序”这个提示自动关闭...
  12. Scala zio-actors与akka-actor集成
  13. 华为s5700交换机IP地址与MAC地址绑定
  14. 3.正态分布概率模型下的最小错误率贝叶斯决策MATLAB程序代码
  15. Magic Leap开发指南(7)-- 眼球追踪(Unity)
  16. C++PrimePlus第5章编程练习答案及运行结果
  17. 抖音直播带货复盘数据怎么分析?3个小技巧快速掌握直播复盘
  18. 用python的turtle模块给女票画个小心心
  19. 给中国学生的第三封信——成功、自信、快乐
  20. xpath解析爬虫爬取豆瓣图书Top250的数据

热门文章

  1. pandas学习task10时序数据
  2. 2022年电工杯赛题A
  3. 查找算法-4种常用的查找算法
  4. 2022-2028年全球及中国多功能示波器行业投资前景分析
  5. M33.搜索旋转排序数组
  6. CSS(长度单位,RGB值,盒子模型)
  7. 51单片机通过两片74HC595级联,用8位LED数码管,分别显示当前日期,如:“2”、“0”、“-”、“0”、“5”、“-”、“2”、“6”,用Proteus仿真实现。
  8. 施努卡:机器视觉系统作用是什么,原理是什么
  9. NLP之基于Transformer的句子翻译
  10. 地理信息系统名词解释大全(一)