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

在该项目中,在Verilog HDL中实现了16位单循环MIPS处理器。 MIPS. 是一个 RISC处理器,许多学术课程中的许多大学广泛应用于计算机组织和架构。 

指令格式和 指令集架构 对于16位单周期MIPS如下:

verilog代码为16位mips cpu
用于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 [rd] = 1如果r [rs]<  R[rt] else 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 + BranchAddr
  10. 添加 I:R [RT] = R [RS] + SIGNEXTIMM
  11. J: PC = JumpAddr.
  12. jal. :r [7] = PC + 2; PC = JumpAddr
  13. SLTI: R [RT] = 1如果r [rs]< imm  else 0
signextimm = {9 {立即[6]},IMM
跳 Addr =.   {(PC + 1)[15:13],地址}
BranchAddr = {7 {立即[6]},立即,1’b0 }

基于所提供的指令集,设计和实现了数据路径和控制单元。

控制单元设计:

控制信号
操作说明
reg
DST.
alusrc.
MEMTO.
reg
reg
Memread.
MEM.
分支
露族
r型
1
0
0
1
0
0
0
00
0
LW.
0
1
1
1
1
0
0
11
0
sw
0
1
0
0
0
1
0
11
0
addi.
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
jal.
2
0
2
1
0
0
0
00
1
SLTI.
0
1
0
1
0
0
0
10
0


alu控制
ALU OP.
功能
alucnt.
alu运作
操作说明
11
XXXX.
000
添加
addi. ,lw,sw
01
XXXX.
001
贝卡
00
00
000
添加
R型:添加
00
01
001
r型:子
00
02
010
R型:和
00
03
011
或者
R型:或
00
04
100
SLT.
R型:SLT
10
xxxxxx.
100
SLT.
I-Type:SLTI

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

完成MIPS处理器的设计后,很容易为MIPS处理器编写Verilog代码。 MIPS处理器整体设计的Verilog代码如下:

Alu单位的Verilog代码
注册文件的Verilog代码
用于指令内存的Verilog代码

数据内存的Verilog代码:

//yl315.net: 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 port  
      input     [15:0]               mem_access_addr,  
      //写端口  
      input     [15:0]               mem_write_data,  
      input                         mem_write_en,  
      input mem_read,  
      // read port  
      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代码:

//yl315.net: FPGA projects, Verilog projects, VHDL projects
// Verilog project: Verilog code for 16-bit MIPS Processor
// Submodule: ALU Control Unit in Verilog 
 module ALUControl( ALU_Control, ALUOp, Function);  
 output reg[2:0] ALU_Control;  
 input [1:0] ALUOp;  
 input [3:0] Function;  
 wire [5:0] ALUControlIn;  
 assign ALUControlIn = {ALUOp,Function};  
 always @(ALUControlIn)  
 casex (ALUControlIn)  
  6'b11 XXXX. : ALU_Control=3'b000;  
  6'b10 XXXX. : ALU_Control=3'b100;  
  6'b01 XXXX. : 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代码:

//yl315.net: 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 // jal  
                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 // beq  
                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 // addi  
                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. 处理器:

//yl315.net: 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 beq_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 imm_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) ? imm_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));  
 // immediate shift 1  
 assign im_shift_1 = {imm_ext[14:0],1'b0};  
 //  
 assign no_sign_ext = ~(im_shift_1) + 1'b1;  
 // PC beq add  
 assign PC_beq = (im_shift_1[15] == 1'b1) ? (pc2 - no_sign_ext): (pc2 +im_shift_1);  
 // beq control  
 assign beq_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 TestBench代码:

 `timescale 1ns / 1ps
//yl315.net: 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  
       结尾   
  终点   
验证单周期MIPS CPU的Verilog代码是非常简单的,通过在Meposeim或Xilinx ISIM上进行多个模拟,以便查看MIPS处理器如何工作。为了完全验证MIPS处理器,需要修改指令存储器以模拟指令集架构中的所有指令,然后检查模拟波形和内存,以查看处理器是否正常工作。 
                                                                  提供的源代码 
Abdrazak Mohammed Anaana

你可能喜欢这个:
Verilog中的32位5级流水线MIPS处理器(第1部分)
Verilog中的32位5级流水线MIPS处理器(Part-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。  VERILOG代码D触发器
19。  完整加法器的Verilog代码
20。  与测试台的计数器的Verilog代码
21。  16位RISC处理器的Verilog代码
22。  FPGA上的按钮的Verilog代码
23。  如何为双向/ inout端口编写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(输入[1:0] ALU_OP,
    input [3:0] funct,
    output JRControl
    );
    分配jrcontrol =({alu_op,funct} == 6'b001000) ? 1'b1 : 1'b0;

    终点
    这里是

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

      删除
    2. 什么是
      港口' ' reg 3 ' '不是reg_file的港口
      港口' ' reg 4 ' '不是reg_file的港口
      在mips_16_bit模块中

      删除
  5. 如何将管道结构实施到MIPS处理器中?我只是在个人阶段之间实施登记册吗?如果是这样,我在哪里实施它们。

    回复 删除
  6. 很快就会有Verilog Post的管道衬里MIP。

    回复 删除
  7. anybdy可以解释工作,我会非常伟大..plz

    回复 删除
  8. 我得到了错误:

    港口' ' reg 3 ' '不是reg_file的港口
    港口' ' reg 4 ' '不是reg_file的港口

    任何帮助吗? :-)

    回复 删除
  9. `时间尺度1ns / 1ps
    模块register_file.
    ( //yl315.net: FPga projects, Verilog projects, VHDL projects
    输入CLK,
    输入RST,
    // write port
    输入reg_write_en,
    输入[2:0] REG_WRITE_DEST,
    输入[15:0] REG_WRITE_DATA,
    //read port 1
    输入[2:0] REG_READ_ADDR_1,
    输出[15:0] REG_READ_DATA_1,
    //read port 2
    输入[2:0] REG_READ_ADDR_2,
    输出[15:0] REG_READ_DATA_2
    );
    reg [15:0] REG_ARRAY [7:0];
    // write port
    //reg [2:0] i;
    总是@(提出乱码或提出的第一次)开始
    if(rst) begin
    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;
    end
    else begin
    如果(REG_WRITE_EN)开始
    reg_array [reg_write_dest]<= reg_write_data;
    end
    end
    end
    分配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.yl315.net/2017/06/32-bit-pipelined-mips-processor-in-verilog-1.html
      http://www.yl315.net/2017/06/32-bit-pipelined-mips-processor-in-verilog-2.html
      http://www.yl315.net/2017/06/32-bit-pipelined-mips-processor-in-verilog-3.html
      请查看32位流水线处理器的Verilog代码

      删除
  11. 港口' ' reg 3 ' '不是reg_file的港口
    港口' ' reg 4 ' '不是reg_file的港口

    回复 删除
    答案
    1. 那'■仅用于模拟中的调试。
      您可以轻松地添加REG3 = REG_ARRAY [3]或REG4 = REG_ARRAY [4]。
      如果你没有,你可以在顶级代码中评论它'想在模拟中看到它。

      删除
  12. http://www.yl315.net/2017/06/32-bit-pipelined-mips-processor-in-verilog-1.html
    http://www.yl315.net/2017/06/32-bit-pipelined-mips-processor-in-verilog-2.html
    http://www.yl315.net/2017/06/32-bit-pipelined-mips-processor-in-verilog-3.html
    请查看32位流水线处理器的Verilog代码

    回复 删除
  13. SIR为16位MIPS的JR_CONTROL代码在哪里?

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

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

      删除
  15. 我有一个问题"Wire [7:0] Ram_Addr = Mem_Access_Addr [9:2];" in the data memory.
    isn.'它每单词内存是一个16位?我认为它可以写作"Wire [7:0] Ram_Addr = mem_access_addr [7:0];只是存储器字对齐MIPS数据访问单元。

    回复 删除
    答案
    1. 谢谢你的问题。它是一个16位CPU,每单词也是如此字节。 PC和偏移地址增加2.所以Ram_Addr = MEM_ACCESS_ADDR [8:1]或ROM_ADDR = PC [4:1]。
      如果使用Wire [7:0] Ram_Addr = MEM_ACCESS_ADDR [7:0],将省略奇数地址(1,3,5,7等)。

      删除
  16. Verilog代码用于可编程优先级编码器?

    回复 删除
  17. 我在Quartus上移动了所有文件,但我如何测试它?

    回复 删除
  18. 有人可以发布单周期MIPS处理器的3级Verilog代码(32位)

    回复 删除
  19. 我可以实现这是代码是成分的吗?
    由于我们使用循环,编译器将显示错误作为难以理解的循环。

    回复 删除
  20. 请为设计单循环MIPS的(32位)处理器提供设计代码,使用Verilog进行R型(添加,子和,或,SLT),I / M型(LW / SW / addi / subi)和beq和j型
    说明(jal,j)。仅考虑整数类型的操作。

    回复 删除
  21. 你好,
    在RTL级别,此代码正确地提供了结果,但在合成此代码时,它会出错。任何想法如何解决这个问题?
    有没有人能够在这方面进行合成仿真。
    谢谢。

    回复 删除
  22. alu_unit和pression_memory何种意义,请分享代码

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

      删除

趋势FPGA项目