《5级流水无cache CPU实验计算机组成原理 课程设计报告.docx》由会员分享,可在线阅读,更多相关《5级流水无cache CPU实验计算机组成原理 课程设计报告.docx(22页珍藏版)》请在三一办公上搜索。
1、5级流水无cache CPU实验计算机组成原理 课程设计报告计算机组成原理 课程设计报告 5级流水无cache CPU实验 1.1 实验内容:无cache流水CPU的分析与改造 1. 理解无cache流水CPU的工作原理,明确系统总体结构和数据通路图,分析解决各种相关用到的主要信号,以及详细分析各流水段的功能和实现。 2. 将16位的指令系统改为8位,设计新的指令系统,并修改相应的数据通路。 3. 修改规则文件(cpu.txt),并编写测试程序验证系统改造的正确性。 1.2 总体基本信息 1. 深刻理解无cache流水cpu的工作原理。在详细分析了各流水段的功能实现、3种相关的产生原因和解决方
2、法的基础上,完成了以下后续工作。 2. 修改指令系统。具体包括: a) 16位指令改为8位,重新编写了指令OP码。 b) 新增了MOVI指令。由于原指令系统没有将立即数存进指定寄存器的指令,因此此处新增一条MOVI指令。指令的汇编语句为 MOVI DR, IMM 其中DR为目的寄存器,IMM为立即数。因为指令长度为8位,OP和DR共占了6位,因此IMM的大小不大于3。 c) 修改及删除了部分指令。此处详见5.1。 3. 修改系统控制信号。在保持原有系统逻辑功能基本不变的情况下,修改各个模块里控制信号位数以及模块接口信号位数以和新的指令系统兼容。 4. 增加内存模块。使用vhdl编写了一个ram
3、模块,根据读写信号来选择读写功能。reset时将事先写好的二进制形式程序写进内存。 5. 扩展了常量定义文件。在常量定义文件unitpack.vhd中,具体地: a) 新增了ALU功能选择信号常量aluMOVI。 b) 新增了寄存器编号常量R0、R1、R2和R3。 c) 新增了ram类型。 6. 使用Quartus II进行功能仿真并debug。 7. 使用bdf构造顶层实体cpum。由于新增了内存模块,而原系统是使用vhdl编写的,为了方便对接,我们使用bdf的形式将无cache流水线cpu和内存模块连接起来构造顶层实体cpum,“m”的含义是“memory”,即带内存模块的无cache流水
4、线cpu。 8. 重画数据通路图。我们使用了Microsoft Visio软件在原有的系统总结结构图的基础上修改并新增了部分模块,详见2。 2、系统总体结构及数据通路图 总体结构图: 2 数据通路图: 整个CPU由以下几个模块组成: l 取指模块:给出内存地址,读取指令并送入指令寄存器,为下一级准备数据。 由于PC控制模块处于取指模块中,因此控制相关的检测也置于取指模块。 l 译码模块:读取寄存器值和指令译码。我们采取一次译码,逐级传递的方式,译出后几级流水所需的控制信号和数据,在每次时钟上升沿到来时送入下一级。实际上,结构相关、控制相关、数据相关的检测都可归入译码部分。考虑到“相关检测”涉及
5、到的信号分属不同阶段以及整体结构的清晰性,我们将“相关检测”独立出来。 l 执行模块:完成算术逻辑运算、计算有效地址和提供数据通道。 l 访存模块:选择地址线的数据来源和数据线的流向。访存和取指在功能上是独立的,但CPU对外只有一条地址线和数据线的事实决定了访存和取指是相互联系的。当执行LOAD/STORE指令时,地址线由ALU送入“访存段”的值提供;取指时,则由PC提供。当写内存时,CPU内部数据送数据线;当需要读内存时,CPU往数据线送高阻。 l 回写模块:选择回写数据源和根据写使能信号wRegEn将数据回写到寄存器堆; l HazardDetectUnit模块:检测结构相关; l For
6、wardingUnit模块:检测数据相关。 l 内存模块memory,根据访存地址mem_adr和读写信号wr来控制。 3 3 解决各种相关用到的主要信号的分析 3.1控制相关 控制相关是指因为程序的执行方向可能改变而引起的相关。当执行跳转指令时,就会发生这种情况。除JR外,JRZ等条件跳转需要根据当前状态位来决定是否跳转,而当前状态位是由前面最近的会影响状态位的指令决定。常规的也是比较简单的做法是在碰到JRX之类的跳转指令时,延迟后边流水线的进入。但我们通过分析,认为可以一点都不必延迟,通过旁路处理把控制相关转为数据相关来处理。这样处理,不必延迟,可以提高流水线的性能。按我们的方式解决控制相
7、关需要做两项工作: 1) 通过旁路,提供状态寄存器的值和临时状态位的值,为判断是否跳转作准备; 2) 选择PC更新的时机 1旁路处理 在每条指令译码时,会产生一个信号setFlag,它决定了在执行阶段是否根据ALU计算结果改变状态位。从下面的时序图中可以发现,只要我们在JRX指令译码时提供以下3个信号就可作出是否跳转的决定: 信号 tFlag Flag e_setFlag 含义 ALU计算出的临时状态位, 状态寄存器输出, 状态寄存器写使能 表17 处理控制相关信号 若e_setFlag要写状态寄存器,则说明前一条指令会影响状态位,这时根据tFlag决定是否跳转;若e_setFlag要保持状态
8、寄存器,则说明前一条指令不会影响状态位,这时根据Flag决定是否跳转。 译码前一条指令取指JR后一条指令译码PC更新取指译码执行4 涉及到控制相关的关键信号是setFlag信号,产生于译码模块,作用于执行模块,即identity.vhdhe exentity.vhd文件中。如下图所示。 从上图可看出,凡是涉及到数值计算和关系运算的指令的低三位均为001,而不涉及的则为000。该信号传到执行模块中用于判断是否更新状态寄存器。 5 3.2 数据相关 数据相关是指在执行本条指令的过程中,如果用到的操作数是前面指令的执行结果,则必须等待前面的指令执行完成,并把结果写回寄存器或主存之后,本条指令才能继续
9、执行。此处采用设置专用数据通路来解决数据相关问题。但旁路技术并非一劳永逸。若前一指令为LOAD,而后一指令和它数据相关,如下图所示,当下一指令的执行阶段需要数据时,上一指令尚未给出,这种情况是无法用旁路技术来解决的。 相关的类型有三种: 1. 2. 6 3. 主要用到的关键信号是m_wRegEn和w_wRegEn,主要使用是在数据相关检测模块forwardingentity.vhd中,在identity.vhd、exentity.vhd、memaccessentity.vhd中均有使用。具体的使用方法如下。 相关的检测都置于“执行阶段”。信号wRegEn是寄存器写使能,SA,SB是寄存器组A,
10、B口选择信号。信号前缀表示信号所处的阶段。如e_SA表示处于执行阶段的SA。 1相邻指令数据相关的检测 若m_wRegEn=1,则表示前一指令要回写寄存器。此时,若e_SA或e_SB等于m_SA,则必然数据相关,这是因为我们规定,若回写寄存器,则寄存器A口选择信号所指定的即为目的寄存器。否则无关。 2 中间隔1条指令的两指令数据相关的检测 若w_wRegEn=1,则表示第一条指令要回写寄存器。此时,若e_SA或e_SB等于w_SA,则必然数据相关。否则无关。 当然,上述两种情况可能会一同出现。这时,我们就按情况1处理。因为情况2可以理解为 接连出现情况1。 7 下图为各个指令在译码时产生的wR
11、egEn信号,可以发现凡是会写进寄存器的指令,该信号值都为1。 8 3.3 结构相关 由于在设计中不包含缓存,因此会有取指和访存的冲突,即结构相关。如下图: 执行访存取指译码取指译码关键信号是wrMem信号,表示是否读写内存。具体出现在结构相关冲突检测与问题解决模块Hazarddetectentity.vhd中,产生于译码模块identity.vhd中。具体使用方法如下: 1) 冲突检测 只有执行访存指令(LOAD/STORE)时,才会出现冲突。因此,我们在译码时产生一个标志是否访存的信号wrMem。含义如下: wrMem 00 01 意义 写内存 读内存 1 不占用内存 表16 wMEM控制
12、信号 通过检查“访存阶段”的m_wrMem就可确定是否冲突。 2)取指延后 在每次取指时,若有冲突,则往IR中写入空指令(NOP),并保持PC不变,使取指延后一个节拍。 9 4 各流水段功能和实现的详细分析 4.1取指(IF) 4.1.1 实现功能列表 取指模块实现的功能是: l 给定内存地址,读取内存中的指令 l 将指令送入指令寄存器,提供给下一级的译码模块 l 实现控制相关冲突检测 l 根据读取到的指令是否为跳转指令来更新PC 4.1.2输入、输出信号分析 主要输入信号: Z,C tempZ,tempC e_setFlag PCStall IFFlush OuterDB 主要输出信号: P
13、C_addr d_PCInc1 状态寄存器 ALU计算出的临时状态位,用于相关冲突检测 状态寄存器写使能端,产生于译码时。决定是否在执行阶段根据ALU计算出来的结果改变状态位 决定是否保持PC不变,由结构相关冲突检测模块产生 决定是否往指令寄存器IR里写入空指令,来自结构相关检测模块 内存读取过来的数据 PC作为内存地址输出,用于下一节拍的取指 PC + 1 10 d_IR 指令寄存器输出 4.1.3功能实现逻辑 通过分析控制信号我们可以大概了解到取指模块的功能实现逻辑是如何的。广义上来说,取指模块包括结构相关冲突检测模块,因为PCStall信号(用来实现IF段对PC的更新)和IFFlush信
14、号(对IR写入空指令)就来自结构相关冲突检测模块。 结构相关检测模块叫HazardDetectEntity,其模块图如下: 其中输入信号的含义是: m_wrMem w_rwMem d_IR wrMem在访存阶段的值 wrMem在写回阶段的值 指令寄存器 通过检测访存阶段的wrMem信号即可确定是否发生了结构冲突。 每次取指后,若有冲突,则往IR中写入空指令,并保持PC不变,使得取指延后一个节拍。 除此之外,setFlag信号在此处的作用是,决定用状态寄存器输出Flag还是ALU计算出的临时状态位tFlag来判断跳转。 4.2译码(ID) 4.2.1 实现功能列表 译码模块实现的功能是: l 读
15、取指令寄存器中的指令 l 对指令进行译码,发送控制信号 11 4.2.2输入、输出信号分析 主要输入信号: d_IR d_PCInc1 w_wbData w_destReg w_wRegEn 主要输出信号: e_RAOut e_RBOut e_IMM e_ALUSrc e_ALUOpr e_SetFlag e_wrMem e_wRegEn 寄存器A输出值 寄存器B输出值 立即数输出值 ALU输入端选择信号 ALU运算选择信号 状态寄存器写使能信号 访存信号 寄存器写使能信号 从取指模块来的指令 从取指模块来的pc+1 写回数据,从写回模块里来 要写回的目标寄存器 寄存器写使能端 12 e_de
16、stReg e_MemToReg 目标寄存器 内存写入寄存器使能信号 4.2.3功能实现逻辑 译码模块内部写好了根据不同的指令发送不同的控制信号的代码,采取一次译码,逐级传递的方式,译出后几级流水所需的控制信号和数据。在每次时钟上升沿到来时送入下一级。实际上,结构相关、控制相关、数据相关的检测都可归入译码部分。考虑到“相关检测”涉及到的信号分属不同阶段以及整体结构的清晰性,作者将“相关检测”独立出来。 4.3执行(EX) 4.3.1 实现功能列表 执行模块实现的功能是: l 根据控制信号完成算术逻辑运算 l 根据控制信号计算有效地址 l 提供数据通道,将上一级传递过来的控制信号传到下一级 13
17、 4.3.2输入、输出信号分析 主要输入信号: e_RAOut、e_RBOut、e_ALUSrc、来自译码模块的控制信号 e_ALUOpr、e_SetFlag、e_IMM、e_memToReg、 e_wRegEn、 forwardA、forwardB e_ALUOut 主要输出信号: m_SA、m_ALUOut、m_RBdata、主要来自上一级模块传过来的控制信号 i_tempZ、i_tempC、m_flag、m_wRegEn、m_memToReg、m_destReg、m_wrMem 来自数据相关冲突检测模块的输出 上一个指令在执行模块产生的输出,作为下一条指令在执行模块执行的输入信号之一 4
18、.3.3功能实现逻辑 执行模块执行的功能很简单,和上个学期做的CPU综合性实验类似,主要是一些ALU逻辑运算和状态寄存器的更新操作。在这里还有向下一模块传递控制信号的作用。 其中,forwardA和forwardB信号是来自数据相关冲突检测模块的信号。 模块图如下所示: 作用是在发生读后写数据相关时,直接将计算好了的结果在写回目标寄存器时也发往下一条指令的执行模块作为ALU的输入之一。 4.4访存(MEM) 4.4.1 实现功能列表 访存模块实现的功能是: l 根据地址线对内存进行读操作或者写操作 14 4.4.2输入、输出信号分析 主要输入信号: m_wrMem m_ALUOut m_RBd
19、ata PC 主要输出信号: w_wrMem wr addr OuterDB 传送到写回模块的内存读写控制信号 读写控制信号 要读取的内存地址 既可作为输入又可作为输出,用于传输数据 内存读写控制信号 来自ALU的输出结果 要写回的数据 程序计数器的值 4.4.3功能实现逻辑 访存和取指在功能上是独立的,但是因为CPU对外只有一条地址线和数据线,因此访存和取指在实际上是有联系和冲突的。当执行Load/Store指令时,地址线由ALU送入访存段的值提供;取指时,则由PC提供。当写内存时,CPU内部数据送往数据线。当需要读内存时,CPU往数据线送高阻。 15 4.5写回(WB) 4.5.1 实现功
20、能列表 写回模块实现的功能是: l 选择写回数据源 l 根据写使能信号wRegEn将数据写回到寄存器组 4.5.2输入、输出信号分析 主要输入信号: s_w_ALUOut s_w_MemOut s_w_memToReg s_w_flag ALU的输出 内存读取的输出 决定写入寄存器的数据来源 要写进状态寄存器的值 4.5.3功能实现逻辑 此部分较为简单,即通过s_w_memToReg信号来决定是将ALU的输出写进寄存器还是将从内存读出来的数据写进寄存器。 模块图如下: 16 5 系统改造 5.1新的指令系统 汇编语句 ADD DR,SR SUB DR,SR CMP DR,SR AND DR,S
21、R OR DR,SR XOR DR,SR SHL DR SHR DR MOV DR,SR LOAD DR,SR STORE DR,SR JR ADR JRC ADR JRZ ADR NOP 操作码 0000 0001 0010 0011 0100 0101 0110 0111 1001 1010 1011 1100 1101 1110 1111 功能描述 DR+SRDR DR-SRDR DR-SR 比较 DR and SRDR 逻辑与 DR or SRDR 逻辑或 DR xor SR DR 异或 逻辑左移,最低位补0,最高位移入C 逻辑右移,最高位补0,最低位移入C IMMDR,存立即数进寄存
22、器 SR DR SR DR SR DR 无条件跳转到ADR , ADR=原PC值+OFFSET 控制转移当C=1时,跳转到ADR, ADR=原PC值+OFFSET 指令 当Z=1时,跳转到ADR, ADR=原PC值+OFFSET 空操作 其他 数据传送指令 指令类型 算术逻辑指令 MOVI DR,IMM 1000 5.1.1选择改动说明 包括NOP空操作指令在内指令系统共包括16条指令,在原有的25条指令的基础上删除了10条,新增了1条。具体地,删除了DEC,INC,TEST,SAR,PUSH,POP,JRNC,JRNZ,LOADH,LOADL,新增了一条数据传送指令MOVI。 5.2修改的代
23、码及说明 1)代码段1,新增内存模块memory.vhd 17 -内存 -2015-10-30 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use work.unitPack.all; ENTITY memory IS PORT ( databus : inout STD_LOGIC_VECTOR(7 DOWNTO 0); -数据总线 addr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -访存地址 wr : IN STD_LOGIC; -读写控制信号 rese
24、t: IN STD_LOGIC ); END memory; ARCHITECTURE rtl OF memory IS SIGNAL ram:ram_type; -ram_type在unitpack.vhd文件里定义 BEGIN PROCESS(addr,wr,ram,databus,reset) BEGIN IF reset=0 THEN ram(0) = MOVI & R0 & 11; -此处将程序写进内存中,省略 ram(15) = JR & 1110; END IF; -读写功能的实现 IF wr=0 THEN databus = Z8; ram(conv_integer(addr)
25、 = databus; END IF; IF wr=1 THEN databus = ram(conv_integer(addr); END IF; END PROCESS; END rtl; 内存模块使用vhdl编写,内存由ram组成,读出数据线和写入数据线为同一条数据总线,因此不能同时进行读写。因为这样所以会产生结构相关,即在取指的时候不可以访存,否则会产生冲突。内存读写功能由wr信号进行控制,当wr为0时执行写功能,当wr为1时执行读功能。 2) 代码段2,取指模块ifentity.vhd 18 op = IR(7 downto 4); -操作码取指令的高4位 -控制相关信号e_setF
26、lag,用于选择当状态寄存器的值来源 with e_setFlag select ZZ = Z when flag_hold, tempZ when others; with e_setFlag select CC = C when flag_hold, -由于跳转信号中只保留了JR、JRC、JRZ,因此此处只判断该3个OP s_selZ = 1 WHEN( op=JRZ AND ZZ=1) -判断是否跳转 OR op=JR else 0; s_selC = 1 WHEN( op=JRC AND CC=1) -判断是否跳转 else 0; PCIncSel = 1 WHEN s_selZ=1
27、or s_selC=1 ELSE 0; s_PCInc1 = PC + x01; -此处修改了PC位数 WITH PCIncSel SELECT -当有跳转时pc = pc + offset,否则pc = pc + PCnext = s_PCInc1 WHEN 0, PCPlusOffset WHEN 1, s_PCInc1 when others; process(reset,clk,PCStall) begin if reset = 0 then PC = x00; -此处修改了PC位数 elsif FALLING_EDGE(clk) and (PCStall=0) then PC ALU
28、Result := opR + opS; tempV := (not opR(7)and(not opS(7)and ALUResult(7) or (opR(7)and opS(7)and (not ALUResult(7); when aluSub = ALUResult := opR - opS; tempV := ( opS(7)and(not opR(7)and (not ALUResult(7) or (NOT opS(7)and opR(7)and ALUResult(7); when aluAnd = ALUResult := opR and opS; when aluOr =
29、 ALUResult := opR or opS; when aluXor = ALUResult := opR xor opS; when aluShl = ALUResult(7 downto 1) := opR(6 downto 0); ALUResult(0) := 0; cx := opR(7); when aluShr = ALUResult(6 downto 0) := opR(7 downto 1); ALUResult(7) := 0; cx := opR(0); -增加了aluMOVI的alu功能选择信号及其处理实现 when aluMOVI = ALUResult :=
30、00000&opS(3 downto 0); when others = null; end case; 修改了alu选择信号以及alu功能信号的判断逻辑,以及状态寄存器的判断逻辑,之所以修改是因为位数的修改。除此以外还增加了aluMOVI的alu功能信号及其对应的逻辑功能实现。 1) 代码段1,译码模块identity.vhd 新增了的 20 WriteBack:process(reset,clk) -写回模块 begin if reset=0 then -新增了初始化寄存器一步 RegArray(0) = x00; RegArray(1) = x00; RegArray(2) = x00;
31、 RegArray(3) = x00; elsif FALLING_EDGE(clk) and w_wRegEn=1 then RegArray(wRegIndex) ctrl:=d_IR(3 downto 0)&10&1&1&001&0000&001; when SUBB = ctrl:=d_IR(3 downto 0)&10&1&1&001&0001&001; when ANDins = ctrl:=d_IR(3 downto 0)&10&1&1&001&0010&001; when CMP = ctrl:=d_IR(3 downto 0)&10&0&1&001&0001&001; -新增
32、了MOVI指令及其译码出来的控制信号 when MOVI = ctrl:=d_IR(3 downto 0)&10&1&1&101&1010&000; imm ctrl:=d_IR(3 downto 0)&10&1&1&001&0011&001; when XORins = ctrl:=d_IR(3 downto 0)&10&1&1&001&0100&001; when SHLIns = ctrl:=d_IR(3 downto 0)&10&1&1&000&0101&001; when SHRIns = ctrl:=d_IR(3 downto 0)&10&1&1&000&0110&001; whe
33、n MOV = ctrl:=d_IR(3 downto 0)&10&1&1&011&0000&000; when LOAD = ctrl:=d_IR(3 downto 0)&01&1&0&011&0000&000; when STORE = ctrl:=d_IR(3 downto 0)&00&0&1&000&0000&000; when JR|JRZ|JRC = ctrl:=DoNothing; -若是JR*指令,计算offset,并向Exe插入Bubble offset ctrl:=DoNothing; end case; 21 译码模块主要修改了控制信号ctrl的位数,并根据“SA, SB
34、, Wrmem, wRegEn, MemToReg, ALUSrc, ALUOpr, SetFlag”的顺序增加了MOVI指令的控制信号,如下所示: when MOVI = ctrl:=d_IR(3 downto 0)&10&1&1&101&1010&000; imm = 000000&d_IR(1 downto 0); 最后还增加了寄存器的初始化。 22 6 测试与总结 6.1 规则文件(cpu.txt的内容) 6.2测试代码 -程序1 -指令正确性测试 - R0 R1 R2 R3 0 0 0 0 -2 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0; 0; - 4 0 -
35、4 4 - 4 1 - 4 1 - 4 4 ram(0) = MOVI & R0 & 11; - 3 0 ram(1) = ADD & R0 & 01; ram(2) = MOV & R1 & R0; ram(3) = SUBB & R1 & 11; ram(5) = ADD & R2 & 11; ram(6) = ORIns & R1 & R0; ram(4) = SUBB & R2 & 10; - 4 1 ram(7) = ANDIns & R1 & R2; - 4 1 ram(8) = XORIns & R0 & R1; - 5 1 ram(9) = SHLIns & R1 & 00;
36、- 5 2 ram(10) = SHRIns & R0 & 00; - 2 2 ram(12) = CMP & R0 & R1; ram(13) = JRC & 1111; ram(11) = LOAD & R0 & R2; - R0的值为ADD & R0 & 01, 即0000 00 01 - CF = 1, ZF = 0 - 跳转到15号地址 ram(14) = MOVI & R3 & 11; - 如果跳转则不执行该指令 ram(15) = STORE & R3 & R0; - 0号地址的内容变为 0000 0001 ram(16) = MOVI & R0 & 11; - R0 = 3 r
37、am(17) = MOVI & R1 & 01; - R1 = 1 ram(18) = SUBB & R0 & R1; ram(19) = JRZ & 1111; ram(20) = JR & 0000; - R0 = R0 R1 - 此处不跳 -此处跳 6.3 测试结果 测试环境 Quartus 测试程序 程序1 测试结果 五级流水 正确 6.4 测试总结 试程序的结果都与预期相符,证明测试结果是正确的。 23 24 7 本课程设计的总结 7.1 A同学总结 由于上一学期在计算机组成原理的综合性实验中担当了主力队员,对cpu的基本组织结构也算是十分了解,因此该学期主动担当了组长。然而事实并没
38、有那么简单,当第一次看到代码时发现,由于上次综合性实验大部分通过画图连线实现,逻辑功能十分明确,一目了然,然而该学期的cpu顶层实体是通过vhdl代码实现的,因此初期花了不少时间在了解代码的语法以及逻辑功能上,完成此步以后,我们组开展了对3种相关进行详细分析。弄清楚流水CPU的实现原理后,后续的修改工作就十分简单了。一开始我们是采用机箱+DebugController的方式进行调试,后来由于实验室的机箱资源有限,便再次采取了用Quartus的时序功能仿真来调试,并添加了内存模块。 7.2B同学总结 在此次课程设计中,我主要:参与修订指令系统;负责数据相关模块的修改;负责译码和访存模块的修改;负责MOVI指令的增加,主要是在常量定义文件unitpack里增加MOVI的op 码常量以及aluMOVI的alu功能选择信号,并在译码模块增加MOVI的控制信号及相关代码;负责扩展常量定义文件。在组长的组织下循序渐进,大部分不懂得问题都能够通过讨论解决。 7.3 C同学总结 在这次的计算机组成原理课程设计里,我负责的是:参与修订指令系统;负责结构相关模块的修改;负责执行模块和写回模块的修改;负责新顶层实体cpum.bdf文件的接线,主要是在创建了cpuentity和memory的bsf文件后,新建cpum.bdf文件并将上述两个原件加入,利用Quartus的接线功能将原件连接起来。 25