logo资料库

基于VHDL语言的单周期MIPS微处理器设计.doc

第1页 / 共19页
第2页 / 共19页
第3页 / 共19页
第4页 / 共19页
第5页 / 共19页
第6页 / 共19页
第7页 / 共19页
第8页 / 共19页
资料共19页,剩余部分请下载后查看
深圳大学研究生课程论文 基于 VHDL 语言的单周期 MIPS 微处理器设计 MIPS 单周期方案是 MIPS 子集最简单的实现方案,主要设计了 12 个模块和一个顶 层文件,实现的指令包括取字(lw),存字(sw),等值分支(beq),不等值则分支(bne),和 算术逻辑指令 add、sub、and、or、nor、逻辑左移(sll)、逻辑右移(srl)和小于则置位(slt), 立即数指令 ori、andi、addi, 跳转指令(J)共 16 条指令。以下是实现方案的各个模块。 一、 程序计数器(PC) PC 其实就是一个 D 触发器,当复位信号(reset)来的时候,同时时钟也到了的时候, 把输入(pc_in)给输出(pc_out),复位的第一个输出是从 x’0000’开始,下面是这个模块的 实现代码: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity PC is port( pc_in : pc_out : clk : reset : end PC; in std_logic_vector(31 downto 0); out std_logic_vector(31 downto 0); in std_logic; in std_logic); architecture Behavioral of PC is begin process(clk,reset,pc_in) begin if reset='1' then pc_out<="00000000000000000000000000000000"; elsif clk='1' and clk'event then pc_out <= pc_in; end if; end process; end Behavioral; 二、 指令地址的计算模块 这个模块的功能是计算指令的地址,由于所选的指令原因,所以有三种指令地址来 源,首先是普通指令的递增,即 PC+4,执行完一条指令后跳转到下一条继续执行;第 二种是相等则分支和不等则分支指令,通过 ALU 的输出 Zero 和控制单元的控制信号 (Branch)相与判断是否选择分支目标地址,分支目标地址的计算方式是:PC+4 的值与符 号扩展并左移 2 位后的指令低 16 位的值相加;第三种是跳转指令 J,跳转指令是无条件 的不同于分支指令,32 位的地址的低 28 位来自 26 位立即数字段左移两位所得,高四位 为当前 PC+4 的最高四位(即顺序下条指令地址的 31:28 位)。下面是代码: library IEEE; 第 1页 共 19页
use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity PC_ADDR is port( pc_out : Jump_addr : Jump,Branch,Zero : sh_l2 : pc_in : out std_logic_vector(31 downto 0)); in std_logic_vector(31 downto 0); in std_logic_vector(25 downto 0); in std_logic; in std_logic_vector(31 downto 0); end PC_ADDR; --Imm_ext shift left 2 architecture Behavioral of PC_ADDR is constant N:integer:=1; begin process(pc_out,Jump_addr,sh_l2,Jump,Branch,Zero) variable pcadd_out : std_logic_vector(31 downto 0); variable Jump_addrout : std_logic_vector(31 downto 0); variable and_out : variable add_out : std_logic; std_logic_vector(31 downto 0); --pc+4 out --pc+4[31-28] & [28-0] --branch and zero --pc+4+sh_l2 begin pcadd_out := pc_out + N; and_out := Branch and Zero; --add_out :=pc_out + N + sh_l2; if Jump = '1' then end if; end process; end Behavioral; Jump_addrout := pcadd_out(31 downto 28) & Jump_addr(25 downto 0) & "00"; pc_in <= Jump_addrout; then elsif and_out = '1' add_out := pcadd_out + sh_l2; pc_in <= add_out; else pc_in <= pcadd_out; 三、 指令存储器(Instr_Mem)模块 这个模块是一个指令存储器,在这里面共写了 16 条指令,通过 reset 初始化在指令 存储器里面,输出为指令的各个部分分别输出,即跳转立即数,opcode,funct,rs,rt, rd,Imm,共有 7 个输出端口。下面是代码: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity InstrMem is 第 2页 共 19页
port( Readaddr : in std_logic_vector(31 downto 0); Reset : in std_logic; Instr_j : out std_logic_vector(25 downto 0); Instr_opcode : out std_logic_vector(5 downto 0); Instr_rs : out std_logic_vector(4 downto 0); Instr_rt : out std_logic_vector(4 downto 0); Instr_rd : out std_logic_vector(4 downto 0); Instr_funct : out std_logic_vector(5 downto 0); Instr_imm : out std_logic_vector(15 downto 0)); end InstrMem; architecture Behavioral of InstrMem is type RAM is array(0 to 31) of std_logic_vector(31 downto 0); signal RAMS:RAM:=(others=>(others=>'0')); signal Instr:std_logic_vector(31 downto 0); begin process(Reset,Readaddr,RAMS) begin if Reset = '1' then RAMS(0)<=conv_std_logic_vector(0,6)&conv_std_logic_vector(18,5)&conv_std_logic _vector(19,5)&conv_std_logic_vector(17,5)&conv_std_logic_vector(0,5)&conv_std_lo gic_vector(32,6); --add $s1,$s2,$s3 加指令 RAMS(1)<=conv_std_logic_vector(0,6)&conv_std_logic_vector(18,5)&conv_std_logi c_vector(19,5)&conv_std_logic_vector(17,5)&conv_std_logic_vector(0,5)&conv_std_l ogic_vector(34,6); --sub $s1,$s2,$s3 减指令 RAMS(2)<=conv_std_logic_vector(12,6)&conv_std_logic_vector(18,5)&conv_std_log ic_vector(17,5)&conv_std_logic_vector(100,16); --andi $s1,$s2,100 与立即数指令 RAMS(3)<=conv_std_logic_vector(35,6)&conv_std_logic_vector(18,5)&conv_std_log ic_vector(17,5)&conv_std_logic_vector(100,16); --lw $s1,100($s2) 取字指令 RAMS(4)<=conv_std_logic_vector(43,6)&conv_std_logic_vector(18,5)&conv_std_log ic_vector(17,5)&conv_std_logic_vector(100,16); --sw $s1,100($s2) 存字指令 RAMS(5)<=conv_std_logic_vector(0,6)&conv_std_logic_vector(18,5)&conv_std_logi c_vector(19,5)&conv_std_logic_vector(17,5)&conv_std_logic_vector(0,5)&conv_std_l ogic_vector(36,6); --and $s1,$s2,$s3 与指令 RAMS(6)<=conv_std_logic_vector(0,6)&conv_std_logic_vector(18,5)&conv_std_logi 第 3页 共 19页
c_vector(19,5)&conv_std_logic_vector(17,5)&conv_std_logic_vector(0,5)&conv_std_l ogic_vector(37,6); --or $s1,$s2,$s3 或指令 RAMS(7)<=conv_std_logic_vector(0,6)&conv_std_logic_vector(18,5)&conv_std_logi c_vector(19,5)&conv_std_logic_vector(17,5)&conv_std_logic_vector(0,5)&conv_std_l ogic_vector(39,6); --nor $s1,$s2,$s3 或非指令 RAMS(8)<=conv_std_logic_vector(13,6)&conv_std_logic_vector(18,5)&conv_std_log ic_vector(17,5)&conv_std_logic_vector(100,16); --ori $s1,$s2,100 或立即数指令 RAMS(9)<=conv_std_logic_vector(0,6)&conv_std_logic_vector(0,5)&conv_std_logic _vector(18,5)&conv_std_logic_vector(17,5)&conv_std_logic_vector(10,5)&conv_std_l ogic_vector(0,6); --sll $s1,$s2,10 逻辑左移指令 RAMS(10)<=conv_std_logic_vector(0,6)&conv_std_logic_vector(0,5)&conv_std_logi c_vector(18,5)&conv_std_logic_vector(17,5)&conv_std_logic_vector(10,5)&conv_std _logic_vector(2,6); --srl $s1,$s2,10 逻辑右移指令 RAMS(11)<=conv_std_logic_vector(4,6)&conv_std_logic_vector(17,5)&conv_std_log ic_vector(18,5)&conv_std_logic_vector(0,16); --beq $s1,$s2,0 相等则分支指令 RAMS(12)<=conv_std_logic_vector(5,6)&conv_std_logic_vector(17,5)&conv_std_log ic_vector(18,5)&conv_std_logic_vector(0,16); --bne $s1,$s2,0 不等则分支指令 RAMS(13)<=conv_std_logic_vector(0,6)&conv_std_logic_vector(18,5)&conv_std_log ic_vector(19,5)&conv_std_logic_vector(17,5)&conv_std_logic_vector(0,5)&conv_std_ logic_vector(42,6); --slt $s1,$s2,$s3 小于则置 1 指令 RAMS(14)<=conv_std_logic_vector(8,6)&conv_std_logic_vector(18,5)&conv_std_log ic_vector(17,5)&conv_std_logic_vector(100,16); --addi $s1,$s2,100 加立即数指令 RAMS(15)<=conv_std_logic_vector(2,6)&conv_std_logic_vector(2500,26); --j 10000 跳转指令 end if; Instr <= RAMS(conv_integer(Readaddr(4 downto 0))); 第 4页 共 19页
end process; Instr_j <= Instr(25 downto 0); Instr_opcode <= Instr(31 downto 26); Instr_rs <= Instr(25 downto 21); Instr_rt <= Instr(20 downto 16); Instr_rd <= Instr(15 downto 11); Instr_imm <= Instr(15 downto 0); Instr_funct <= Instr(5 downto 0); end Behavioral; 四、 控制单元模块(Opcode_Ctrl) 指 令 的 [31-26] 部 分 的 opcode 产 生 一 系 列 的 控 , 其 中 RegDst,Jump,Branch,MemRead,ALUOp,MemWrite,ALUSrc,RegWrite 八个,通过 case 语 句来实现。下面是代码: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity Opcode_Ctrl is port( Opcode : in std_logic_vector(5 downto 0); RegDst,Branch,MemRead,MemWrite,ALUSrc,MemtoReg,Jump, RegWrite : ALUOp : end Opcode_Ctrl; out std_logic; out std_logic_vector(2 downto 0)); architecture Behavioral of Opcode_Ctrl is begin process(Opcode) begin --R case Opcode is when "000000" => RegDst<='1';ALUSrc<='0';MemtoReg<='0';RegWrite<='1'; MemRead<='0';MemWrite<='0';Branch<='0';ALUOp<="100";Jump<='0'; when "100011" => RegDst<='0';ALUSrc<='1';MemtoReg<='1';RegWrite<='1'; MemRead<='1';MemWrite<='0';Branch<='0';ALUOp<="000";Jump<='0'; when "101011" => RegDst<='0';ALUSrc<='1';MemtoReg<='1';RegWrite<='0'; MemRead<='0';MemWrite<='1';Branch<='0';ALUOp<="000";Jump<='0'; when "000100" => RegDst<='0';ALUSrc<='0';MemtoReg<='0';RegWrite<='0'; MemRead<='0';MemWrite<='0';Branch<='1';ALUOp<="010";Jump<='0'; when "000101" => RegDst<='0';ALUSrc<='0';MemtoReg<='0';RegWrite<='0'; --bne --beq --lw --sw 第 5页 共 19页
--J --ori MemRead<='0';MemWrite<='0';Branch<='1';ALUOp<="011";Jump<='0'; when "000010" => RegDst<='0';ALUSrc<='1';MemtoReg<='0';RegWrite<='0'; MemRead<='0';MemWrite<='0';Branch<='0';ALUOp<="011";Jump<='1'; when "001101" => RegDst<='0';ALUSrc<='1';MemtoReg<='0';RegWrite<='1'; MemRead<='0';MemWrite<='0';Branch<='0';ALUOp<="101";Jump<='0'; when "001100" => RegDst<='0';ALUSrc<='1';MemtoReg<='0';RegWrite<='1'; MemRead<='0';MemWrite<='0';Branch<='0';ALUOp<="110";Jump<='0'; when "001000" => RegDst<='0';ALUSrc<='1';MemtoReg<='0';RegWrite<='1'; MemRead<='0';MemWrite<='0';Branch<='0';ALUOp<="111";Jump<='0'; when others => null ; end case; end process; --andi --addi end Behavioral; 五、 多路复用模块(寄存器写端口的来源) 由于不同的指令的目标寄存器地址不同,R 指令的目标寄存器 rd,I 指令的目标寄 存器是 rt,通过 RegDet 控制信号实现目标寄存器的区分。下面是代码: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity DRMUX1 is port(RegDst : rt,rd : DR : out std_logic_vector(4 downto 0)); in std_logic; in std_logic_vector(4 downto 0); end DRMUX1; architecture Behavioral of DRMUX1 is begin DR <= rt when RegDst = '0' else rd when RegDst = '1'; end Behavioral; 六、寄存器堆(REG) 寄存器堆是一个 RAM 寄存器,里面存放的是 32 位的数据,指令通过 rs,rt,和 rd 字段 给出寄存器号的地址,读出或写入数据 。在寄存器堆里面,当复位信号来的时候,初 始化 17,18,19 三个寄存器为,里面的值分别是 2,3,4。各条指令使用的指令寄存器 都是这三个。下面是代码: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; 第 6页 共 19页
entity REG is port(SR1,SR2,DR : in std_logic_vector(4 downto 0); CLK,RST : in std_logic; Reg_In : in std_logic_vector(31 downto 0); RegWrite : in std_logic; Readdate1,Readdate2 : out std_logic_vector(31 downto 0)); end REG; architecture Behavioral of REG is type RAM is array (31 downto 0) of std_logic_vector(31 downto 0); signal Regs : RAM :=(others =>(others =>'1')); begin --初始化寄存器堆 process(CLK,RST,Reg_In) begin if RST='1' then Regs(17) <= "00000000000000000000000000000010"; Regs(18) <= "00000000000000000000000000000011"; Regs(19) <= "00000000000000000000000000000100"; --初始化 17 号寄存器 --初始化 18 号寄存器 --初始化 19 号寄存器 elsif CLK='1' and CLK'event then if RegWrite='1' then Regs(CONV_INTEGER(DR)) <= Reg_In; end if; end if; END process; Readdate1 <= Regs(CONV_INTEGER(SR1)); Readdate2 <= Regs(CONV_INTEGER(SR2)); end Behavioral; 七、 符号扩展单元,同时对其左移两位(codeext) 这个模块的功能是对指令的 16 位立即数进行符号扩展,扩转时要注意 16 位最高位 是’0’还是’1’,当为’0’ 时高 16 位为 x”000”,当为’1’时高 16 位位 x”ffff”;输出有两个, 一个是扩展后的 32 数据,用于立即数指令,另一个是左移两个,作为分支指令的地址 来源。下面是代码: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; 第 7页 共 19页
entity CodeExt is port(Imm : in std_logic_vector(15 downto 0); Imm_Ext : inout std_logic_vector(31 downto 0); out std_logic_vector(31 downto 0)); sh_l2 : end CodeExt; --32 位左移 2 位后的输出 architecture Behavioral of CodeExt is begin Imm_Ext <= x"0000" & Imm when Imm(15)='0' else x"FFFF" & Imm; sh_l2 <= Imm_Ext(29 downto 0) & "00" ; end Behavioral; 八、 ALU 多路选择模块 这个模块的功能是选择 ALU 的一个输入,这个输入有两个来源,其中一个是立即 数扩转成的 32 位数据,在立即数指令中使用,另外一个是寄存器堆的第二个输出,在 R 类型指令和分支指令中使用,控制信号是 ALUSrc 和指令的 funct 字段。下面是代码: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ALUMUX2 is port(Readdate2,Imm_Ext : ALUSrc : ALU_InB : out std_logic_vector(31 downto 0)); in std_logic_vector(31 downto 0); in std_logic; end ALUMUX2; architecture Behavioral of ALUMUX2 is begin ALU_InB <= Readdate2 when ALUSrc='0' Imm_Ext when ALUSrc='1'; else end Behavioral; 九、ALUCtrl 模块 这个模块的功能是由控制信号 ALUOp 实现控制 ALU 操作,不同的指令要求不同 的 ALU 操作,由 Opcode 所得的 ALUOp 控制。下面是代码: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ALU_Ctrl is port( ALUOp : in std_logic_vector(2 downto 0); 第 8页 共 19页
分享到:
收藏