用于16位单周期MIPS处理器的Verilog代码

在此项目中,Verilog HDL中实现了16位单周期MIPS处理器。 MIPS 是一个 RISC处理器,已被许多大学广泛用于与计算机组织和架构相关的学术课程。 

指令格式和 指令集架构 16位单周期MIPS的情况如下:

适用于16位MIPS CPU的Verilog代码
MIPS 处理器的指令集
 MIPS 处理器的Verilog代码
MIPS 处理器的指令集架构

以下是在Verilog中实现的说明的说明:


  1. 加:R [rd] = R [rs] + R [rt]
  2. 减:R [rd] = R [rs]-R [rt]
  3. 并且:R [rd] = R [rs]& R[rt]
  4. 或:R [rd] = R [rs] | R [rt]
  5. SLT: 如果R [rs],则R [rd] = 1<  R[rt] 否则0
  6. Jr:PC = R [rs]
  7. Lw:R [rt] = M [R [rs] + SignExtImm]
  8. Sw:M [R [rs] + SignExtImm] = R [rt]
  9. Beq:if(R [rs] == R [rt])PC = PC + 1 + 科 Addr
  10. Addi:R [rt] = R [rs] + SignExtImm
  11. PC = 跳 Addr
  12. Jal:R [7] = PC + 2; PC = 跳 Addr
  13. SLTI: 如果R [rs],则R [rt] = 1<  else 0
SignExtImm = {9 {immediate [6]},imm
跳 Addr =   {(PC + 1)[15:13],地址}
科 Addr = {7 {immediate [6]},立即,1’b0 }

根据提供的指令集,设计并实现数据路径和控制单元。

控制单元设计:

控制信号
指令
注册
Dst
ALUSrc
门托
注册
注册
记忆读
m
R型
1
0
0
1
0
0
0
00
0
轻量级
0
1
1
1
1
0
0
11
0
西南
0
1
0
0
0
1
0
11
0
阿迪
0
1
0
1
0
0
0
11
0
贝克
0
0
0
0
0
0
1
01
0
j
0
0
0
0
0
0
0
00
1
贾尔
2
0
2
1
0
0
0
00
1
ti
0
1
0
1
0
0
0
10
0


ALU控制
ALU op
功能
ALU操作
指令
11
xxx
000
Addi,lw,sw
01
xxx
001
潜艇
BEQ
00
00
000
R型:ADD
00
01
001
潜艇
R型:子
00
02
010
R型:与
00
03
011
要么
R型:或
00
04
100
slt
R型:SLT
10
xxx xx
100
slt
i型:slti

mips处理器的Verilog代码
16位MIPS处理器的数据路径和控制单元

完成MIPS处理器的设计后,可以很容易地为MIPS处理器编写Verilog代码。用于MIPS处理器整个设计的Verilog代码如下:

ALU单元的Verilog代码
寄存器文件的Verilog代码
指令存储器的Verilog代码

数据存储器的Verilog代码:

//hzgifts.cn: FPGA projects, Verilog projects, VHDL projects
// Verilog project: Verilog code for 16-bit  MIPS  Processor
// Submodule: Data memory in Verilog 
 module data_memory  
 (  
      input                         clk,  
      // address input, shared by read and write 港口 
      input     [15:0]               mem_access_addr,  
      // write 港口 
      input     [15:0]               mem_write_data,  
      input                         mem_write_en,  
      input mem_read,  
      // read 港口 
      output     [15:0]               mem_read_data  
  );   
      integer i;  
      reg [15:0] ram [255:0];  
      wire [7 : 0] ram_addr = mem_access_addr[8 : 1];  
      initial begin  
           for(i=0;i<256;i=i+1)  
                ram[i] <= 16'd0;  
       结束   
      always @(posedge clk) begin  
           if (mem_write_en)  
                ram[ram_addr] <= mem_write_data;  
       结束   
      assign mem_read_data = (mem_read==1'b1) ? ram[ram_addr]: 16'd0;   
  终端模块    

ALU控制单元的Verilog代码:

//hzgifts.cn: FPGA projects, Verilog projects, VHDL projects
// Verilog project: Verilog code for 16-bit  MIPS  Processor
// Submodule: ALU控制 Unit in Verilog 
 module ALUControl( ALU_Control,  铝 ,  功能  );   
 output reg[2:0] ALU_Control;  
 input [1:0]  铝 ;  
 input [3:0]  功能 ;  
 wire [5:0] ALUControlIn;  
 assign ALUControlIn = {ALUOp,Function};  
 always @(ALUControlIn)  
 casex (ALUControlIn)  
  6'b11 xxx : ALU_Control=3'b000;  
  6'b10 xxx : ALU_Control=3'b100;  
  6'b01 xxx : ALU_Control=3'b001;  
  6'b000000: ALU_Control=3'b000;  
  6'b000001: ALU_Control=3'b001;  
  6'b000010: ALU_Control=3'b010;  
  6'b000011: ALU_Control=3'b011;  
  6'b000100: ALU_Control=3'b100;  
  default: ALU_Control=3'b000;  
   结束 case  
  终端模块   
// Verilog code for JR control unit
module JR_Control( input[1:0] alu_op, 
       input [3:0] funct,
       output JRControl
     ); 
assign JRControl = ({alu_op,funct}==6'b001000) ? 1'b1 : 1'b0;
 终端模块 

控制单元的Verilog代码:

//hzgifts.cn: FPGA projects, Verilog projects, VHDL projects
// Verilog project: Verilog code for 16-bit  MIPS  Processor
// Submodule: Control Unit in Verilog 
 module control( input[2:0] opcode,  
                           input reset,  
                           output reg[1:0] reg_dst,mem_to_reg,alu_op,  
                           output reg jump,branch,mem_read,mem_write,alu_src,reg_write,sign_or_zero                      
    );   
 always @(*)  
 begin  
      if(reset == 1'b1) begin  
                reg_dst = 2'b00;  
                mem_to_reg = 2'b00;  
                alu_op = 2'b00;  
                jump = 1'b0;  
                branch = 1'b0;  
                mem_read = 1'b0;  
                mem_write = 1'b0;  
                alu_src = 1'b0;  
                reg_write = 1'b0;  
                sign_or_zero = 1'b1;  
       结束   
      else begin  
      case(opcode)   
      3'b000: begin // add  
                reg_dst = 2'b01;  
                mem_to_reg = 2'b00;  
                alu_op = 2'b00;  
                jump = 1'b0;  
                branch = 1'b0;  
                mem_read = 1'b0;  
                mem_write = 1'b0;  
                alu_src = 1'b0;  
                reg_write = 1'b1;  
                sign_or_zero = 1'b1;  
                 结束   
      3'b001: begin // sli  
                reg_dst = 2'b00;  
                mem_to_reg = 2'b00;  
                alu_op = 2'b10;  
                jump = 1'b0;  
                branch = 1'b0;  
                mem_read = 1'b0;  
                mem_write = 1'b0;  
                alu_src = 1'b1;  
                reg_write = 1'b1;  
                sign_or_zero = 1'b0;  
                 结束   
      3'b010: begin // j  
                reg_dst = 2'b00;  
                mem_to_reg = 2'b00;  
                alu_op = 2'b00;  
                jump = 1'b1;  
                branch = 1'b0;  
                mem_read = 1'b0;  
                mem_write = 1'b0;  
                alu_src = 1'b0;  
                reg_write = 1'b0;  
                sign_or_zero = 1'b1;  
                 结束   
      3'b011: begin //  贾尔   
                reg_dst = 2'b10;  
                mem_to_reg = 2'b10;  
                alu_op = 2'b00;  
                jump = 1'b1;  
                branch = 1'b0;  
                mem_read = 1'b0;  
                mem_write = 1'b0;  
                alu_src = 1'b0;  
                reg_write = 1'b1;  
                sign_or_zero = 1'b1;  
                 结束   
      3'b100: begin // lw  
                reg_dst = 2'b00;  
                mem_to_reg = 2'b01;  
                alu_op = 2'b11;  
                jump = 1'b0;  
                branch = 1'b0;  
                mem_read = 1'b1;  
                mem_write = 1'b0;  
                alu_src = 1'b1;  
                reg_write = 1'b1;  
                sign_or_zero = 1'b1;  
                 结束   
      3'b101: begin // sw  
                reg_dst = 2'b00;  
                mem_to_reg = 2'b00;  
                alu_op = 2'b11;  
                jump = 1'b0;  
                branch = 1'b0;  
                mem_read = 1'b0;  
                mem_write = 1'b1;  
                alu_src = 1'b1;  
                reg_write = 1'b0;  
                sign_or_zero = 1'b1;  
                 结束   
      3'b110: begin //  贝克   
                reg_dst = 2'b00;  
                mem_to_reg = 2'b00;  
                alu_op = 2'b01;  
                jump = 1'b0;  
                branch = 1'b1;  
                mem_read = 1'b0;  
                mem_write = 1'b0;  
                alu_src = 1'b0;  
                reg_write = 1'b0;  
                sign_or_zero = 1'b1;  
                 结束   
      3'b111: begin //  阿迪   
                reg_dst = 2'b00;  
                mem_to_reg = 2'b00;  
                alu_op = 2'b11;  
                jump = 1'b0;  
                branch = 1'b0;  
                mem_read = 1'b0;  
                mem_write = 1'b0;  
                alu_src = 1'b1;  
                reg_write = 1'b1;  
                sign_or_zero = 1'b1;  
                 结束   
      default: begin  
                reg_dst = 2'b01;  
                mem_to_reg = 2'b00;  
                alu_op = 2'b00;  
                jump = 1'b0;  
                branch = 1'b0;  
                mem_read = 1'b0;  
                mem_write = 1'b0;  
                alu_src = 1'b0;  
                reg_write = 1'b1;  
                sign_or_zero = 1'b1;  
                 结束   
       结束 case  
       结束   
  结束   
  终端模块   

单周期的Verilog代码 MIPS 处理器:

//hzgifts.cn: FPGA projects, Verilog projects, VHDL projects
// Verilog project: Verilog code for 16-bit  MIPS  Processor
 // Verilog code for 16 bit single cycle  MIPS  CPU  
 module mips_16( input clk,reset,  
                           output[15:0] pc_out, alu_result
                           //,reg3,reg4  
    );   
 reg[15:0] pc_current;  
 wire signed[15:0] pc_next,pc2;  
 wire [15:0] instr;  
 wire[1:0] reg_dst,mem_to_reg,alu_op;  
 wire jump,branch,mem_read,mem_write,alu_src,reg_write     ;  
 wire     [2:0]     reg_write_dest;  
 wire     [15:0] reg_write_data;  
 wire     [2:0]     reg_read_addr_1;  
 wire     [15:0] reg_read_data_1;  
 wire     [2:0]     reg_read_addr_2;  
 wire     [15:0] reg_read_data_2;  
 wire [15:0] sign_ext_im,read_data2,zero_ext_im,imm_ext;  
 wire JRControl;  
 wire [2:0] ALU_Control;  
 wire [15:0] ALU_out;  
 wire zero_flag;  
 wire signed[15:0] im_shift_1, PC_j, PC_beq, PC_4beq,PC_4beqj,PC_jr;  
 wire  贝克 _control;  
 wire [14:0] jump_shift_1;  
 wire [15:0]mem_read_data;  
 wire [15:0] no_sign_ext;  
 wire sign_or_zero;  
 // PC   
 always @(posedge clk or posedge reset)  
 begin   
      if(reset)   
           pc_current <= 16'd0;  
      else  
           pc_current <= pc_next;  
  结束   
 // PC + 2   
 assign pc2 = pc_current + 16'd2;  
 // instruction memory  
 instr_mem instrucion_memory(.pc(pc_current),.instruction(instr));  
 // jump shift left 1  
 assign jump_shift_1 = {instr[13:0],1'b0};  
 // control unit  
 control control_unit(.reset(reset),.opcode(instr[15:13]),.reg_dst(reg_dst)  
                ,.mem_to_reg(mem_to_reg),.alu_op(alu_op),.jump(jump),.branch(branch),.mem_read(mem_read),  
                .mem_write(mem_write),.alu_src(alu_src),.reg_write(reg_write),.sign_or_zero(sign_or_zero));  
 // multiplexer regdest  
 assign reg_write_dest = (reg_dst==2'b10) ? 3'b111: ((reg_dst==2'b01) ? instr[6:4] :instr[9:7]);  
 // register file  
 assign reg_read_addr_1 = instr[12:10];  
 assign reg_read_addr_2 = instr[9:7];  
 register_file reg_file(.clk(clk),.rst(reset),.reg_write_en(reg_write),  
 .reg_write_dest(reg_write_dest),  
 .reg_write_data(reg_write_data),  
 .reg_read_addr_1(reg_read_addr_1),  
 .reg_read_data_1(reg_read_data_1),  
 .reg_read_addr_2(reg_read_addr_2),  
 .reg_read_data_2(reg_read_data_2)); 
 //.reg3(reg3),  
 //.reg4(reg4));  
 // sign extend  
 assign sign_ext_im = {{9{instr[6]}},instr[6:0]};  
 assign zero_ext_im = {{9{1'b0}},instr[6:0]};  
 assign  嗯 _ext = (sign_or_zero==1'b1) ? sign_ext_im : zero_ext_im;  
 // JR control  
 JR_Control JRControl_unit(.alu_op(alu_op),.funct(instr[3:0]),.JRControl(JRControl));       
 // ALU control unit  
 ALUControl ALU_Control_unit(.ALUOp(alu_op),.Function(instr[3:0]),.ALU_Control(ALU_Control));  
 // multiplexer alu_src  
 assign read_data2 = (alu_src==1'b1) ?  嗯 _ext : reg_read_data_2;  
 // ALU   
 alu alu_unit(.a(reg_read_data_1),.b(read_data2),.alu_control(ALU_Control),.result(ALU_out),.zero(zero_flag));  
 //  嗯 ediate shift 1  
 assign im_shift_1 = {imm_ext[14:0],1'b0};  
 //  
 assign no_sign_ext = ~(im_shift_1) + 1'b1;  
 // PC  贝克  add  
 assign PC_beq = (im_shift_1[15] == 1'b1) ? (pc2 - no_sign_ext): (pc2 +im_shift_1);  
 //  贝克  control  
 assign  贝克 _control = branch & zero_flag;  
 // PC_beq  
 assign PC_4beq = (beq_control==1'b1) ? PC_beq : pc2;  
 // PC_j  
 assign PC_j = {pc2[15],jump_shift_1};  
 // PC_4beqj  
 assign PC_4beqj = (jump == 1'b1) ? PC_j : PC_4beq;  
 // PC_jr  
 assign PC_jr = reg_read_data_1;  
 // PC_next  
 assign pc_next = (JRControl==1'b1) ? PC_jr : PC_4beqj;  
 // data memory  
 data_memory datamem(.clk(clk),.mem_access_addr(ALU_out),  
 .mem_write_data(reg_read_data_2),.mem_write_en(mem_write),.mem_read(mem_read),  
 .mem_read_data(mem_read_data));  
 // write back  
 assign reg_write_data = (mem_to_reg == 2'b10) ? pc2:((mem_to_reg == 2'b01)? mem_read_data: ALU_out);  
 // output  
 assign pc_out = pc_current;  
 assign alu_result = ALU_out;  
  终端模块   

单周期MIPS处理器的Verilog测试平台代码:

 `timescale 1ns / 1ps
//hzgifts.cn: FPGA projects, Verilog projects, VHDL projects
// Verilog project: Verilog code for 16-bit  MIPS  Processor
// Testbench Verilog code for 16 bit single cycle  MIPS  CPU  
 module tb_mips16;  
      // Inputs  
      reg clk;  
      reg reset;  
      // Outputs  
      wire [15:0] pc_out;  
      wire [15:0] alu_result;//,reg3,reg4;  
      // Instantiate the Unit Under Test (UUT)  
      mips_16 uut (  
           .clk(clk),   
           .reset(reset),   
           .pc_out(pc_out),   
           .alu_result(alu_result)  
           //.reg3(reg3),  
          // .reg4(reg4)  
       );   
      initial begin  
           clk = 0;  
           forever #10 clk = ~clk;  
       结束   
      initial begin  
           // Initialize Inputs  
           //$monitor ("register 3=%d, register 4=%d", reg3,reg4);  
           reset = 1;  
           // Wait 100 ns for global reset to finish  
           #100;  
     reset = 0;  
           // Add stimulus here  
       结束   
  终端模块   
通过在ModelSim或Xilinx ISIM上进行几次仿真来验证MIPS处理器的工作原理,验证单周期MIPS CPU的Verilog代码非常简单。为了完全验证MIPS处理器,需要修改指令存储器以模拟指令集体系结构中的所有指令,然后检查模拟波形和存储器以查看处理器是否按设计正常工作。 
                                                                  源代码提供者 
阿卜杜拉萨克·穆罕默德·阿纳纳

您可能会这样:
Verilog中的32位5级流水线MIPS处理器(第1部分)
Verilog中的32位5级流水线MIPS处理器(第2部分)
Verilog中的32位5级流水线MIPS处理器(第3部分)

16位RISC处理器的Verilog代码
MIPS 处理器的VHDL代码
推荐的 Verilog projects:
2. FIFO存储器的Verilog代码
3. 用于16位单周期MIPS处理器的Verilog代码
4. Verilog HDL中的可编程数字延迟计时器
5. 用于数字电路中基本逻辑组件的Verilog代码
6. 用于32位无符号除法器的Verilog代码
7. 用于定点矩阵乘法的Verilog代码
8. Verilog HDL中的车牌许可证识别
9. 提前进位乘法器的Verilog代码
10。  微处理器的Verilog代码
11。  4x4乘法器的Verilog代码
12  停车场系统的Verilog代码
13  使用Verilog HDL在FPGA上进行图像处理
14。  如何使用Verilog HDL将文本文件加载到FPGA中
15  交通信号灯控制器的Verilog代码
16。  FPGA上的闹钟的Verilog代码
17。  比较器设计的Verilog代码
18岁  D触发器的Verilog代码
19  Full Adder的Verilog代码
20  带testbench的计数器的Verilog代码
21  16位RISC处理器的Verilog代码
22  用于在FPGA上反跳按钮的Verilog代码
23。  如何为双向/输入端口编写Verilog Testbench
28。  解码器的Verilog代码
29。  复用器的Verilog代码
FPGA Verilog VHDL课程

34条评论:

  1. 我可以和您一起检查一下我必须在试验台代码中包括哪种类型的刺激。我用测试台运行了整个程序100ns,但寄存器值为0或x

    回复 删除
  2. 仔细检查您的指令存储器。此处的所有说明均已完全验证。
    您可以按指令检查指令,并查看寄存器文件,数据存储器以进行验证。

    回复 删除
  3. 好的,谢谢您的建议。我还有另一个问题,当我编译程序时,出现以下错误:
    错误(12006):节点实例"JR_Control_unit"实例化未定义的实体"JR_Control"

    有人知道如何解决吗?

    回复 删除
  4. 模块JR_Control(input [1:0] alu_op,
    输入[3:0]功能,
    输出JRControl
    );
    分配JRControl =({alu_op,funct} == 6'b001000) ? 1'b1 : 1'b0;

    终端模块
    这里是

    回复 删除
    回覆
    1. 非常感谢你的帮助!

      删除
    2. 什么是
      港口' ' reg 3 ' ' is not a 港口of reg_file
      港口' ' reg 4 ' ' is not a 港口of reg_file
      在mips_16_bit模块中

      删除
  5. 如何在MIPS处理器中实现流水线结构?我是否只是在各个阶段之间实施注册?如果是这样,我在哪里实现它们。

    回复 删除
  6. 即将在Verilog中发布管道式MIPS。

    回复 删除
  7. 谁能解释一下工作原理,我将非常感激..plz

    回复 删除
  8. 我收到错误:

    港口' ' reg 3 ' ' is not a 港口of reg_file
    港口' ' reg 4 ' ' is not a 港口of reg_file

    有什么帮助吗? :-)

    回复 删除
  9. `时标1ns / 1ps
    模块register_file
    ( //hzgifts.cn: FPga projects, Verilog projects, VHDL projects
    输入clk
    输入第一个
    // write 港口
    输入reg_write_en,
    输入[2:0] reg_write_dest,
    输入[15:0] reg_write_data,
    //read 港口1
    输入[2:0] reg_read_addr_1,
    输出[15:0] reg_read_data_1,
    //read 港口2
    输入[2:0] reg_read_addr_2,
    输出[15:0] reg_read_data_2
    );
    reg [15:0] reg_array [7:0];
    // write 港口
    // reg [2:0] i;
    总是@(posege clk或posege rst)开始
    如果开始
    reg_array [0]<= 15'b0;
    reg_array [1]<= 15'b0;
    reg_array [2]<= 15'b0;
    reg_array [3]<= 15'b0;
    reg_array [4]<= 15'b0;
    reg_array [5]<= 15'b0;
    reg_array [6]<= 15'b0;
    reg_array [7]<= 15'b0;
    结束
    否则开始
    if(reg_write_en)开始
    reg_array [reg_write_dest]<= reg_write_data;
    结束
    结束
    结束
    分配reg_read_data_1 =(reg_read_addr_1 == 0)? 15'b0:reg_array [reg_read_addr_1];
    分配reg_read_data_2 =(reg_read_addr_2 == 0)? 15'b0:reg_array [reg_read_addr_2];
    终端模块

    回复 删除
    回覆
    1. 我试过了,但最终输出只是输出'z's ???我想我不知道这里应该发生什么

      删除
  10. 请发布带有数据路径和控制单元说明的32位流水线risc处理器的Verilog代码

    回复 删除
    回覆
    1. http://www.hzgifts.cn/2017/06/32-bit-pipelined-mips-processor-in-verilog-1.html
      http://www.hzgifts.cn/2017/06/32-bit-pipelined-mips-processor-in-verilog-2.html
      http://www.hzgifts.cn/2017/06/32-bit-pipelined-mips-processor-in-verilog-3.html
      请检查一下用于32位流水线处理器的Verilog代码

      删除
  11. 港口' ' reg 3 ' ' is not a 港口of reg_file
    港口' ' reg 4 ' ' is not a 港口of reg_file

    回复 删除
    回覆
    1. 那'仅用于仿真调试。
      您可以轻松添加reg3 = reg_array [3]或reg4 = reg_array [4]。
      如果您不这样做,则可以在顶级代码中将其注释掉'不想在仿真中看到它。

      删除
  12. http://www.hzgifts.cn/2017/06/32-bit-pipelined-mips-processor-in-verilog-1.html
    http://www.hzgifts.cn/2017/06/32-bit-pipelined-mips-processor-in-verilog-2.html
    http://www.hzgifts.cn/2017/06/32-bit-pipelined-mips-processor-in-verilog-3.html
    请检查一下用于32位流水线处理器的Verilog代码

    回复 删除
  13. 先生,16位MIPS的JR_Control代码在哪里?

    回复 删除
  14. 16位风险和16位mips处理器之间有什么区别。我读到mips是基于风险的处理器!

    回复 删除
    回覆
    1. 我已经在帖子中提到过,MIPS是RISC处理器。

      删除
  15. 我有一个问题"电线[7:0] ram_addr = mem_access_addr [9:2];" in the data memory.
    Isn'每个字存储一个16位吗?我认为可以写成"电线[7:0] ram_addr = mem_access_addr [7:0];。只需一个存储字即可对齐MIPS数据访问单元。

    回复 删除
    回覆
    1. 感谢您的提问。它是一个16位CPU,因此每个字2个字节。 PC和偏移地址增加2。因此ram_addr = mem_access_addr [8:1]或rom_addr = PC [4:1]。
      如果您使用导线[7:0] ram_addr = mem_access_addr [7:0],则将忽略奇数地址(1、3、5、7等)。

      删除
  16. 可编程优先编码器的Verilog代码?

    回复 删除
  17. 我将所有文件都移到了quartus上,但是如何测试呢?

    回复 删除
  18. 有人可以为单周期MIPS处理器(32位)发布3 STAGE verilog代码吗

    回复 删除
  19. 我可以实现这个代码是iverilog吗?
    因为如果使用循环,编译器将错误显示为无法理解的循环。

    回复 删除
  20. 请提供使用Verilog设计基于MIPS的单周期(32位)处理器的代码,以获取有关R型(ADD,SUB,AND,OR,SLT),I / M型(LW / 西南 )的指令/ 加 I / 潜艇 I)和BEQ和J型
    说明(JAL,J)。仅考虑整数类型的操作。

    回复 删除
  21. 你好
    在RTL级别上,此代码正确给出了结果,但是在合成该代码时却给出了错误。任何想法如何解决这个问题?
    有谁能够对此进行后期合成模拟。
    谢谢。

    回复 删除
  22. 请问alu_unit和instruction_memory如何共享代码?

    回复 删除
    回覆
    1. 所有代码都共享,这两个链接也都在帖子中共享。

      删除

热门FPGA项目