PARWANCPU状态机设计基于FPGA数字系统设计

基于FPGA的数字系统设计 大作业 学号:
姓名:
班级:
题目一:设计Parwan 的control section 内部状态机s1\s2\..\s9\,并给出功能仿真? 题目二:利用分层结构设计ParwanCPU,并给出功能仿真? (利用在实验课中所给出的TESTBENCH)
实验原理图 Control Section Structure:s1…s9(如下图所示)
Inputs and outputs of PARWAN control sections: –Applied to, categories, signal name, functions 实验过程 1.1 创建工程 (1)
打开ISE13.x软件,选择File->New Project在弹出的对话框中输入工程名和路径。

(2)
单击下一步选择所使用的芯片。Spartan3E开发板的芯片型号为Spartan3E XC3S500E芯片,FG320封装。

(3)
单击Next,进入工程信息页面,确认无误后,点击Finish完成工程的创建。

1.2 测试文件 (1) 选择菜单栏中的Project->New Source。

(2) 在Select Source Type窗口中,选择左侧的VHDL Test Bench,在右侧File Name栏中输入文件名par_control_unit_tb (3) 单击Next按钮,选择关联文件。

1.3 实验截图 实验代码 在实现过程中,除了定义CPU的信号接口外,还设置了一个输出类型的接口,名字叫present_state_value,主要是用来在调试或仿真的过程中输出CPU所处的状态,便于调试分析。

整个状态机的实现过程主要使用了case … IS … when 逻辑结构。用了present_state 和next_state两个状态变量。详细的实现代码如下所示:
LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE work.synthesis_utilities.ALL; -- ENTITY par_control_unit IS PORT (clk : IN std_logic; -- register control signals: load_ac, zero_ac, load_ir, increment_pc, load_page_pc, load_offset_pc, reset_pc, load_page_mar, load_offset_mar, load_sr, cm_carry_sr, -- bus connection control signals: pc_on_mar_page_bus, ir_on_mar_page_bus, pc_on_mar_offset_bus, dbus_on_mar_offset_bus, pc_offset_on_dbus, obus_on_dbus, databus_on_dbus, mar_on_adbus, dbus_on_databus, -- logic unit function control outputs: arith_shift_left, arith_shift_right : OUT std_logic; alu_and,alu_not,alu_a,alu_add,alu_b,alu_sub: out std_logic; -- inputs from the data section: ir_lines : IN std_logic_vector (7 DOWNTO 0); status : IN std_logic_vector (3 DOWNTO 0); -- memory control and other external signals: read_mem, write_mem : OUT std_logic; interrupt : IN std_logic; --test present_state_value: out std_logic_vector (3 DOWNTO 0) ); END par_control_unit; -- ARCHITECTURE dataflow_synthesizable OF par_control_unit IS TYPE cpu_states IS (s1,s2,s3,s4,s5,s6,s7,s8,s9); SIGNAL present_state, next_state : cpu_states; SIGNAL next_state_value: std_logic_vector (3 DOWNTO 0); BEGIN clocking : PROCESS (clk, interrupt) BEGIN IF (interrupt = '1') THEN present_state <= s1; present_state_value <=“0001“; ELSIF clk'EVENT AND clk = '0' THEN present_state <= next_state; present_state_value <=next_state_value; END IF; END PROCESS clocking; -- sequencing : PROCESS ( present_state, ir_lines, status, interrupt) BEGIN load_ac <= '0'; zero_ac <= '0'; load_ir <= '0'; increment_pc <= '0'; load_page_pc <= '0'; load_offset_pc <= '0'; reset_pc <= '0'; load_page_mar <= '0'; load_offset_mar <= '0'; load_sr <= '0'; cm_carry_sr <= '0'; -- bus connection control signals: pc_on_mar_page_bus <= '0'; ir_on_mar_page_bus <= '0'; pc_on_mar_offset_bus <= '0'; dbus_on_mar_offset_bus <= '0'; pc_offset_on_dbus <= '0'; obus_on_dbus <= '0'; databus_on_dbus <= '0'; mar_on_adbus <= '0'; dbus_on_databus <= '0'; -- logic unit function control outputs: arith_shift_left <= '0'; arith_shift_right <= '0'; alu_and <='0';alu_not <='0';alu_a <='0';alu_add <='0';alu_b <='0';alu_sub <='0'; -- memory control and other external signals: read_mem <= '0'; write_mem <= '0'; CASE present_state IS WHEN s1 => -------------------------------------------1 IF (interrupt = '1') THEN reset_pc <= '1'; next_state <= s1; next_state_value <=“0001“; ELSE pc_on_mar_page_bus <= '1'; pc_on_mar_offset_bus <= '1'; load_page_mar <= '1'; load_offset_mar <= '1'; next_state <= s2; next_state_value <=“0010“; END IF; WHEN s2 => ---------------------------------------2 -- read memory into ir mar_on_adbus <= '1'; read_mem <= '1'; databus_on_dbus <= '1'; alu_a <= '1'; load_ir <= '1'; increment_pc <= '1'; next_state <= s3; next_state_value <=“0011“; WHEN s3 => --------------------------------------3 pc_on_mar_page_bus <= '1'; pc_on_mar_offset_bus <= '1'; load_page_mar <= '1'; load_offset_mar <= '1'; IF (ir_lines (7 DOWNTO 4) /= “1110“) THEN next_state <= s4; next_state_value <=“0100“; ELSE CASE ir_lines (3 DOWNTO 0) IS WHEN “0001“ => --cla zero_ac <= '1'; load_ac <= '1'; WHEN “0100“ => --cmc cm_carry_sr <= '1'; WHEN “1000“ => --asl alu_b <= '1'; arith_shift_left <= '1'; load_sr <= '1'; load_ac <= '1'; WHEN “1001“ => --asr alu_b <= '1'; arith_shift_right <= '1'; load_sr <= '1'; load_ac <= '1'; WHEN OTHERS => NULL; END CASE; next_state <= s2; next_state_value <=“0010“; END IF; WHEN s4 => ----------------------------------------4 -- read memory into mar offset mar_on_adbus <= '1'; read_mem <= '1'; databus_on_dbus <= '1'; dbus_on_mar_offset_bus <= '1'; load_offset_mar <= '1'; IF ( ir_lines (7 DOWNTO 6) /= “11“ ) THEN ir_on_mar_page_bus <= '1'; load_page_mar <= '1'; IF ( ir_lines (4) = '1' ) THEN next_state <= s5; next_state_value <=“0101“; ELSE next_state <= s6; next_state_value <=“0110“; END IF; ELSE --jsr or bra, do not alter mar -- page IF ( ir_lines (5) = '0' ) THEN -- jsr next_state <= s7; next_state_value <=“0111“; ELSE next_state <= s9; next_state_value <=“1001“; END IF; END IF; increment_pc <= '1'; WHEN s5 => ---------------------------------------5 -- read actual operand from memory into mar -- offset mar_on_adbus <= '1'; read_mem <= '1'; databus_on_dbus <= '1'; dbus_on_mar_offset_bus <= '1'; load_offset_mar <= '1'; next_state <= s6; next_state_value <=“0110“; WHEN s6 => --------------------------------------6 IF ( ir_lines (7 DOWNTO 5) = “100“ ) THEN --jmp load_page_pc <= '1'; load_offset_pc <= '1'; next_state <= s2; next_state_value <=“0010“; ELSIF ( ir_lines (7 DOWNTO 5) = “101“ ) THEN -- mar on adbus, ac on databus, write --to memory mar_on_adbus <= '1'; alu_b<= '1'; obus_on_dbus <= '1'; dbus_on_databus <= '1'; write_mem <= '1'; next_state <= s1; next_state_value <=“0001“; ELSIF ( ir_lines (7) = '0' ) THEN ------ --lda, and, add, sub -- mar on adbus, read memory for --operand, perform operation mar_on_adbus <= '1'; read_mem <= '1'; databus_on_dbus <= '1'; IF ( ir_lines (6) = '0' ) THEN ---- lda, and IF ( ir_lines (5) = '0' ) THEN -- lda alu_a<= '1'; ELSE -- and alu_and<= '1'; END IF; ELSE ---- add, sub IF ( ir_lines (5) = '0' ) THEN -- add alu_add<= '1'; ELSE -- sub alu_sub<= '1'; END IF; END IF; load_sr <= '1'; load_ac <= '1'; next_state <= s1; next_state_value <=“0001“; END IF; WHEN s7 => --------------------------------------------7 -- write pc offset to top of subroutine mar_on_adbus <= '1'; pc_offset_on_dbus <= '1'; dbus_on_databus <= '1'; write_mem <= '1'; load_offset_pc <= '1'; next_state <= s8; next_state_value <=“1000“; WHEN s8 => --------------------------------------8 increment_pc <= '1'; next_state <= s1; next_state_value <=“0001“; WHEN s9 => -----------------------------------------9 IF ( all_or (status AND ir_lines (3 DOWNTO 0)) = '1') THEN load_offset_pc <= '1'; END IF; next_state <= s1; next_state_value <=“0001“; 实验原理 实验过程 2.1 创建工程 (1)
打开ISE13.x软件,选择File->New Project在弹出的对话框中输入工程名和路径。

(2)
单击下一步选择所使用的芯片。Spartan3E开发板的芯片型号为Spartan3E XC3S500E芯片,FG320封装。

(3)
单击Next,进入工程信息页面,确认无误后,点击Finish完成工程的创建。

2.2 设计输入 选择Project->Add copy of source,将实验的源代码添加到工程中。

2.3 综合实现 (1)
编写汇编测试代码 (2)用文本编辑器打开实验源代码中的simple.asm文件。

(3)将测试代码转换为内存文件 (4)编译并执行程序 2.4 设计仿真 2.5 结果截图 编写testbench代码对以上的状态机进行功能仿真。Testbench的核心代码如下:
stim_proc: process begin -- hold reset state for 100 ns. wait for 10 ns; ir_lines <= “01101111“; --SUB loc wait for clk_period*10; ir_lines <= “10001111“; --JMP loc wait for clk_period*10; ir_lines <= “10101111“; --STA loc wait for clk_period*10; ir_lines <= “11111000“; --BRA_V_addr wait for clk_period*10; ir_lines <= “11100001“; --CLA wait for clk_period*10; end process; 由上代码可见,在测试波形中,选取了4种ir_line的可能值来测试。下面选择两处仿真波形进行分析:
图5.1 “STA loc” 仿真波形图 从“STA loc” 仿真波形图中,连续的时钟周期里,ir_line的值都为“10101111”,可知该指令是“STA 1111”。结合parwan的状态转换关系来看,一开始CPU处于s1状态,由于interrupt=‘0’,转到s2状态,再转到s3状态,由于ir_line(7to4)!=”1110”,转到s4状态,由于ir_line(7to4)=”11X0”转到s6状态,最后由于ir_line(7to5)=”1010”转回s1,完成一次循环周期。还可以看到在相应的状态,相应的信号会被设为“1”,如s1中,信号load_page_mar、load_offset_mar、pc_on_mar_page_bus和pc_on_mar_offset_bus等信号为“1”,状态机的设计相符。

图5.2 “CLA” 仿真波形图 从“CLA” 仿真波形图中,我们主要从黄线部分开始往后看,在这的一个时钟周期后ir_line的值都为“11100001”,parwan的指令集可知指令是“CLA”。结合parwan的状态设计来看,一开始CPU处于s1状态,由于interrupt=‘0’,转到s2状态,再转到s3状态,由于ir_line(7to4)=”1110”,转到s2状态,最后在s2和s3中循环。验证了程序的正确性。

实验总结:本次作业以以前四次上机为基础,通过利用上机所得的实验能力和部分实验代码,进行本次的Parwan CPU设计,基本上来说,本次作业要比上机更有难度,首先,进行的一次综合性实验,其次,上机时均给出了实验步骤。但不可否认的是,本次实验更能提高我们对Parwan CPU的理解,对提高我们的实验能力更有帮助。

推荐访问:设计 数字 系统