制作多周期CPU(代码)
来源:互联网 发布:数据侠客行txt网盘 编辑:程序博客网 时间:2024/06/16 05:38
MCPU
module MCPU( CLK, RST, CurPC, instcode ); input CLK; // 时钟信号 input RST; // 置零信号 output [31:0] CurPC; // 当前指令的地址 output [31:0] instcode; // 指令寄存器中获取的指令码 wire [5:0] op; // 操作码 wire [4:0] rs; wire [4:0] rt; wire [4:0] rd; wire [4:0] sa; // 移位指令的移动位数 wire [15:0] immediate; // I类型指令的立即数(未被扩展) wire [25:0] address; // J类型指令跳转的地址(未被扩展) wire [31:0] NextPC; // 下一条指令的地址 wire [31:0] PC4; // PC正常+4后的值,即临近下一个的地址 wire [31:0] BeqPC; // 对于beq指令成立时要跳转的目标地址 wire [31:0] JumpPC; // 对于jal、j指令要跳转的目标地址 wire ExtSel; // 位扩展信号,1为符号扩展,0为0扩展 wire PCWre; // PC工作信号,0不更改,1更改 wire InsMemRW; // 指令寄存器信号,0为写,1为读 wire IRWre; // IR寄存器从指令寄存器中获取指令代码 wire WrRegDSrc; // 如果是jal指令,此时要选择31号寄存器保存当前PC wire [1:0] RegDst; // 指令读取时判断是rt还是rd还是31号寄存器进入寄存器组的写数据端,00为31号,01为rt,10为rd wire RegWre; // 寄存器组是否需要写功能,0为无写功能,1为写功能 wire [2:0] ALUOP; // ALU8种运算功能选择 wire [1:0] PCSrc; // 选择下一条PC的值,00为正常PC+4,01为beq执行的跳转,10为jr指令跳转到31号寄存器保存的地址,11为j和jal指令 wire ALUSrcA; // 寄存器组Data1的输出,0为寄存器本身输出,1为指令码的最后16位立即数 wire ALUSrcB; // 寄存器组Data2的输出,0位本身的输出,1为扩展后的立即数 wire RD; // 读数据存储器功能,0时读取 wire WR; // 写数据存储器功能,1时写 wire DBDataSrc; // 决定将什么数据传入寄存器组Write Data端,0为ALU结果,1为存储器 wire [4:0] WriteRegAddr; // 寄存器组Write Reg输入端 wire [31:0] Reg1Out; // 寄存器组rs寄存器的值 wire [31:0] Reg2Out; // 寄存器组rt寄存器的值,也是存储器的DataIn输入端 wire [31:0] WriteData; // 寄存器组Write Data输入端的值 wire [31:0] ALU_Input_A; // ALU的A输入端 wire [31:0] ALU_Input_B; // ALU的B输入端 wire [31:0] ALU_Out; // ALU的result输出,也是存储器的地址输入端 wire zero; // ALU的zero输出 wire [31:0] MemOut; // 存储器的输出 wire [31:0] Ext_Imm; // 位扩展后的立即数 wire [31:0] ADR_Out; wire [31:0] BDR_Out; wire [31:0] ALUOutDR_Out; wire [31:0] DBDR_In; wire [31:0] DBDR_Out; // PC( CLK, RST, PCWre, NextPC, CurPC ) PC my_PC( CLK, RST, PCWre, NextPC, CurPC ); // ALU_For_Next( CurPC, PC4 ) ALU_For_Next my_ALU_For_Next( CurPC, PC4 ); // ALU_For_Beq( PC4, Aim, BeqPC ) ALU_For_Beq my_ALU_For_Beq( PC4, Ext_Imm, BeqPC ); // Mux_FourToOne_PC( PC4, BeqPC, JrPC, JumpPC, PCSrc, NextPC) Mux_FourToOne_PC my_Mux_FourToOne_PC( PC4, BeqPC, Reg1Out, JumpPC, PCSrc, NextPC); // InstructionMemory( CurPC, InstMemRW, instcode ) InstructionMemory my_InstructionMemory( CurPC, InsMemRW, instcode ); // IR( CLK, instcode, IRWre, op, rs, rt, rd, sa, immediate, address ) IR my_IR( CLK, instcode, IRWre, op, rs, rt, rd, sa, immediate, address ); // Extend_For_Address( PC4, Address, JumpPC ) Extend_For_Address my_Extend_For_Address( PC4, address, JumpPC ); // Mux_ThreeToOne_WriteReg( rt, rd, RegDst, WriteReg ) Mux_ThreeToOne_WriteReg my_Mux_ThreeToOne_WriteReg( rt, rd, RegDst, WriteRegAddr ); // Mux_TwoToOne_Data( Select, DataA, DataB, DataOut ) Mux_TwoToOne_Data my_MuxTwoToOne_For_WriteData( WrRegDSrc, PC4, DBDR_Out, WriteData ); // Sign_Zero_Extend( Imm_Number, ExtSel, Result ) Sign_Zero_Extend my_Sign_Zero_Extend( immediate, ExtSel, Ext_Imm ); // RegisterFile( RegWre, CLK, Reg1, Reg2, WriteReg, WriteData, DataOut1, DataOut2 ) RegisterFile my_RegisterFile( RegWre, CLK, rs, rt, WriteRegAddr, WriteData, Reg1Out, Reg2Out ); // DR( CLK, DataIn, DataOut ) DR my_ADR( CLK, Reg1Out, ADR_Out ); // DR( CLK, DataIn, DataOut ) DR my_BDR( CLK, Reg2Out, BDR_Out ); // Mux_TwoToOne_For_InputA( ALUSrcA, DataIn, sa, DataOut ) Mux_TwoToOne_For_InputA my_Mux_TwoToOne_For_InputA( ALUSrcA, ADR_Out, sa, ALU_Input_A ); // Mux_TwoToOne_Data( Select, DataA, DataB, DataOut ) Mux_TwoToOne_Data my_Mux_TwoToOne_For_InputB( ALUSrcB, BDR_Out, Ext_Imm, ALU_Input_B ); // ALU( Reg1, Reg2, ALUOp, result, zero ) ALU my_ALU( ALU_Input_A, ALU_Input_B, ALUOP, ALU_Out, zero ); // DR( CLK, DataIn, DataOut ) DR my_ALUOutDR( CLK, ALU_Out, ALUOutDR_Out ); // DataMemory( CLK, DAddr, RD, WR, DataIn, DataOut ) DataMemory my_DataMemory( CLK, ALUOutDR_Out, RD, WR, BDR_Out, MemOut ); // Mux_TwoToOne_Data( Select, DataA, DataB, DataOut ) Mux_TwoToOne_Data my_MuxTwoToOne_For_DBDR( DBDataSrc, ALU_Out, MemOut, DBDR_In ); // DR( CLK, DataIn, DataOut ) DR my_DBDR( CLK, DBDR_In, DBDR_Out ); // ControlUnit( CLK, RST, zero, op, DBDataSrc, WR, RD, ALUSrcB, ALUSrcA, ALUOP, RegWre, RegDst, WrRegDSrc, IRWre, InsMemRW, PCWre, ExtSel, PCSrc ) ControlUnit my_ControlUnit( CLK, RST, zero, op, DBDataSrc, WR, RD, ALUSrcB, ALUSrcA, ALUOP, RegWre, RegDst, WrRegDSrc, IRWre, InsMemRW, PCWre, ExtSel, PCSrc );endmodule
PC
module PC( CLK, RST, PCWre, NextPC, CurPC ); input CLK, RST, PCWre; input [31:0] NextPC; output reg [31:0] CurPC; /*initial begin Address = 0; end*/ always @( negedge CLK or negedge RST ) begin if (RST == 0) begin CurPC = 0; end else if (PCWre) begin CurPC = NextPC; end endendmodule
ALU_For_Next
module ALU_For_Next( CurPC, PC4 ); input [31:0] CurPC; output reg [31:0] PC4; always@( CurPC ) begin PC4 = CurPC + 4; endendmodule
ALU_For_Beq
module ALU_For_Beq( PC4, Aim, BeqPC ); input [31:0] PC4, Aim; output reg [31:0] BeqPC; always@( PC4 or Aim ) begin BeqPC = PC4 + Aim * 4; endendmodule
Mux_FourToOne_PC
module Mux_FourToOne_PC( PC4, BeqPC, JrPC, JumpPC, PCSrc, NextPC ); input [31:0] PC4, BeqPC, JrPC, JumpPC; input [1:0] PCSrc; output reg [31:0] NextPC; always@( PC4 or BeqPC or JrPC or JumpPC or PCSrc ) begin case ( PCSrc ) 2'b00 : NextPC = PC4; 2'b01 : NextPC = BeqPC; 2'b10 : NextPC = JrPC; 2'b11 : NextPC = JumpPC; endcase endendmodule
InstructionMemory
module InstructionMemory( CurPC, InstMemRW, instcode ); input [31:0] CurPC; input InstMemRW; output reg [31:0] instcode; reg [7:0] InstMemory [255:0]; initial begin $readmemb("H:/CPU/Multiple_CPU/instruction.txt", InstMemory); end always@( CurPC or InstMemRW ) begin if (InstMemRW == 1) begin instcode = { InstMemory[CurPC], InstMemory[CurPC + 1], InstMemory[CurPC + 2], InstMemory[CurPC + 3] }; end $display("InstMem PC", CurPC, " INST: ", instcode); endendmodule
IR
module IR( CLK, instcode, IRWre, op, rs, rt, rd, sa, immediate, address ); input CLK; input [31:0] instcode; input IRWre; output reg [5:0] op; output reg [4:0] rs, rt, rd, sa; output reg [15:0] immediate; output reg [25:0] address; always@( negedge CLK ) begin if (IRWre == 1) begin op = instcode[31:26]; rs = instcode[25:21]; rt = instcode[20:16]; rd = instcode[15:11]; sa = instcode[10:6]; immediate = instcode[15:0]; address = instcode[25:0]; end endendmodule
Extend_For_Address
module Extend_For_Address( PC4, Address, JumpPC ); input [31:0] PC4; input [25:0] Address; output reg [31:0] JumpPC; always@( PC4 or Address ) begin JumpPC = { PC4[31:28], Address[25:0], 2'b00 }; endendmodule
Mux_ThreeToOne_WriteReg
module Mux_ThreeToOne_WriteReg( rt, rd, RegDst, WriteReg ); input [4:0] rt, rd; input [1:0] RegDst; output reg [4:0] WriteReg; always@( rt or rd or RegDst ) begin case(RegDst) 2'b00 : WriteReg = 5'b11111; 2'b01 : WriteReg = rt; 2'b10 : WriteReg = rd; endcase endendmodule
Mux_TwoToOne_Data
module Mux_TwoToOne_Data( Select, DataA, DataB, DataOut ); input Select; input [31:0] DataA, DataB; output reg [31:0] DataOut; always@( Select or DataA or DataB ) begin if (Select == 0) DataOut = DataA; else DataOut = DataB; endendmodule
Sign_Zero_Extend
module Sign_Zero_Extend( Imm_Number, ExtSel, Result ); input [15 :0] Imm_Number; input ExtSel; output reg [31:0] Result; always@( Imm_Number or ExtSel) begin if (ExtSel == 0 || Imm_Number[15] == 0) Result = { 16'b0000000000000000, Imm_Number }; else Result = { 16'b1111111111111111, Imm_Number }; endendmodule
RegisterFile
module RegisterFile( RegWre, CLK, Reg1, Reg2, WriteReg, WriteData, DataOut1, DataOut2 ); input RegWre; input CLK; input [4:0] Reg1, Reg2; input [4:0] WriteReg; input [31:0] WriteData; output [31:0] DataOut1, DataOut2; reg [31:0] registers[1:31]; assign DataOut1 = ( Reg1 == 0 ) ? 0 : registers[Reg1]; assign DataOut2 = ( Reg2 == 0 ) ? 0 : registers[Reg2]; always@( posedge CLK ) begin // 写操作 $display("RegWre: ", RegWre); if (( WriteReg != 0 ) && ( RegWre )) begin $display("WriteData: ", WriteData, " WriteReg: ", WriteReg); registers[WriteReg] <= WriteData; end endendmodule
DR
module DR( CLK, DataIn, DataOut ); input CLK; input [31:0] DataIn; output reg [31:0] DataOut; always@( negedge CLK ) begin DataOut <= DataIn; endendmodule
Mux_TwoToOne_For_InputA
module Mux_TwoToOne_For_InputA( ALUSrcA, DataIn, sa, DataOut ); input ALUSrcA; input [31:0] DataIn; input [4:0] sa; output reg [31:0] DataOut; always@( ALUSrcA or DataIn or sa ) begin if ( ALUSrcA == 0 ) DataOut = DataIn; else DataOut = { 27'b000000000000000000000000000, sa }; // 对sa进行扩展 endendmodule
ALU
module ALU( Reg1, Reg2, ALUOp, result, zero ); input [31:0] Reg1; input [31:0] Reg2; input [2:0] ALUOp; output reg [31:0] result; output zero; assign zero = ( result == 0 ) ? 1 : 0; always@( ALUOp or Reg1 or Reg2 ) begin case (ALUOp) 3'b000 : result = Reg1 + Reg2; // Y = A + B 3'b001 : result = Reg1 - Reg2; // Y = A - B 3'b010 : begin if (Reg1 < Reg2 && ((Reg1[31] == 0 && Reg2[31] == 0) || (Reg1[31] == 1 && Reg2[31] == 1))) result = 1; else if (Reg1[31] == 0 && Reg2[31] == 1) result = 0; else if (Reg1[31] == 1 && Reg2[31] == 0) result = 1; else result = 0; end 3'b011 : result = (Reg1 < Reg2) ? 1 : 0; // Y=(A < B)? 1 : 0 3'b100 : result = Reg2 << Reg1; // Y = B << A 3'b101 : result = Reg1 | Reg2; // Y = A | B 3'b110 : result = Reg1 & Reg2; // Y = A & B 3'b111 : result = Reg1 ^ Reg2; // Y = A ^ B endcase endendmodule
DataMemory
module DataMemory( CLK, DAddr, RD, WR, DataIn, DataOut ); input CLK; input [31:0] DAddr; input RD; input WR; input [31:0] DataIn; output reg [31:0] DataOut; reg [7:0] dataMemory [0:60]; always@( * ) begin // 读,随时的 if (RD == 0) begin DataOut[7:0] = dataMemory[DAddr + 3]; DataOut[15:8] = dataMemory[DAddr + 2]; DataOut[23:16] = dataMemory[DAddr + 1]; DataOut[31:24] = dataMemory[DAddr]; end end always@( posedge CLK ) begin // 写,时钟上升沿触发 if (WR == 0) begin dataMemory[DAddr + 3] <= DataIn[7:0]; dataMemory[DAddr + 2] <= DataIn[15:8]; dataMemory[DAddr + 1] <= DataIn[23:16]; dataMemory[DAddr] <= DataIn[31:24]; end endendmodule
ControlUnit
module ControlUnit( CLK, RST, zero, op, DBDataSrc, WR, RD, ALUSrcB, ALUSrcA, ALUOP, RegWre, RegDst, WrRegDSrc, IRWre, InsMemRW, PCWre, ExtSel, PCSrc ); input CLK, RST, zero; input [5:0] op; output reg DBDataSrc, WR, RD, ALUSrcB, ALUSrcA; output reg [2:0] ALUOP; output reg RegWre; output reg [1:0] RegDst; output reg WrRegDSrc, IRWre, InsMemRW, PCWre, ExtSel; output reg [1:0] PCSrc; reg [2:0] CurState, NextState; initial begin CurState = 3'b000; NextState = 3'b001; end always@( RST ) begin if (RST) begin CurState = 3'b000; NextState = 3'b001; end end always@( posedge CLK ) begin if (RST == 1) begin CurState = NextState; /* * 状态转换阶段 */ end end always@( * ) begin if (op == 6'b000000 || op == 6'b000001 || op == 6'b000010 || op == 6'b010000 || op == 6'b010001 || op == 6'b010010 || op == 6'b011000 || op == 6'b100110 || op == 6'b100111) begin NextState[2] = CurState[2] ^ CurState[0]; NextState[1] = CurState[2] ^ CurState[0]; NextState[0] = ~CurState[0]; end if (op == 6'b110100) begin NextState[2] = ~CurState[2] & CurState[0]; NextState[1] = 0; NextState[0] = ~CurState[2]; end if (op == 6'b110001) begin NextState[2] = CurState[1] & CurState[0]; NextState[1] = CurState[1] ^ CurState[0]; NextState[0] = ~CurState[2] & ~CurState[0]; end if (op == 6'b110000) begin NextState[2] = 0; NextState[1] = CurState[1] ^ CurState[0]; NextState[0] = ~CurState[0]; end if (op == 6'b111000 || op == 6'b111010 || op == 6'b111001 || op == 6'b111111) begin NextState[2] = 0; NextState[1] = 0; NextState[0] = ~CurState[0]; end case (CurState) 3'b000 : begin // IF PCWre = (op == 6'b111111) ? 0 : 1; InsMemRW = 1; IRWre = 0; RD = 1; WR = 1; RegWre = 0; end 3'b001 : begin // ID PCWre = 0; ExtSel = (op == 6'b010010) ? 0 : 1; IRWre = 1; WrRegDSrc = (op == 6'b111010) ? 0 : 1; if (op == 6'b111010) RegDst = 2'b00; else if (op == 6'b000010 || op == 6'b010010 ||op == 6'b100111 || op == 6'b110001) RegDst = 2'b01; else RegDst = 2'b10; PCSrc[0] = (op == 6'b111010 || op == 6'b111000) ? 1 : 0; PCSrc[1] = (op == 6'b111001 || op == 6'b111010 || op == 6'b111000) ? 1 : 0; RegWre = (op == 6'b111010) ? 1 : 0; end 3'b110 : begin // EXE for add,sub,addi,or,and,ori,slt,slti,sll IRWre = 0; ALUOP[0] = (op == 6'b000001 || op == 6'b010000 || op == 6'b010010) ? 1 : 0; ALUOP[1] = (op == 6'b010001 || op == 6'b100110 || op == 6'b100111) ? 1 : 0; ALUOP[2] = (op == 6'b010000 || op == 6'b010001 || op == 6'b010010 || op == 6'b011000) ? 1 : 0; ALUSrcA = (op == 6'b011000) ? 1 : 0; ALUSrcB = (op == 6'b000010 || op == 6'b010010 || op == 6'b100111) ? 1 : 0; DBDataSrc = 0; end 3'b101 : begin // EXE for beq IRWre = 0; ALUOP = 3'b001; ALUSrcA = 0; ALUSrcB = 0; PCSrc = (zero == 1) ? 2'b01 : 2'b00; end 3'b010 : begin //EXE for sw,lw IRWre = 0; ALUOP = 3'b000; ALUSrcA = 0; ALUSrcB = 1; DBDataSrc = 1; end 3'b011 : begin // MEM for sw,lw RD = (op == 6'b110001) ? 0 : 1; WR = (op == 6'b110000) ? 0 : 1; end 3'b111 : begin // WB for add,sub,addi,or,and,ori,slt,slti,sll RD = 1; WR = 1; RegWre = 1; end 3'b100 : begin // WB for lw RD = 1; WR = 1; RegWre = 1; end endcase endendmodule
阅读全文
0 0
- 制作多周期CPU(代码)
- 制作单周期CPU(代码)
- 制作多周期CPU(分析)
- 制作单周期CPU(分析)
- cpu周期(机器周期)
- MIPS多周期CPU设计(Verilog)
- 多周期cpu设计(verilog)
- 多周期CPU设计
- 多周期CPU设计
- 多周期CPU实验
- 多周期CPU实验
- 精确测量代码的CPU运行周期
- (Verilog)多周期CPU设计
- 多周期CPU设计(Verilog) (更新:2017/5/29)
- 多周期cpu设计与实现
- #计组实验#多周期CPU设计
- MIPS单周期CPU设计(Verilog)
- 单周期CPU实验之代码实现及模拟
- 数据结构(队列--两个栈实现)
- 基于Eclipse的web开发实践之安装spring插件
- matlab并行运算方法
- 数字图像处理——用Java对图像做镜像变换
- docker
- 制作多周期CPU(代码)
- JavaWeb学习随笔(一) id name property相关,以及一般项目的流程
- Android View的绘制过程
- 智能一代云平台(二十四):已安装的Nginx上安装echo
- MQ在分布式系统中的应用于协作
- 避免死锁的进阶指导
- 安装Abaqus6.13+VS2012+Fortran后,Abaqus卡顿解决办法
- MySQL 远程连接
- iOS崩溃crash大解析