多周期cpu设计(verilog)

Posted sysu_zjl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多周期cpu设计(verilog)相关的知识,希望对你有一定的参考价值。

由于之前设计过单周期,所以这里很多模块都是类似的

我是把所有数据选择器的模块都单独拿出来,这里主要有
32位的4选1数据选择器,5位的3选1选择器,32位的2选1选择器,对于pc+4、j和jal指令跳转的pc值都单独变成一个模块
上代码
写control unit时要根据不同的指令并且不同的状态发出不同的信号,其他信号为默认信号

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    14:24:34 05/12/2016 
// Design Name: 
// Module Name:    sc_cpu 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module sc_cpu(op, func, z, clock, resetn,
             wpc, wir, Inswmem, Datawmem, wreg, regrt, m2reg, aluc, alusrcb, pcsource, sext, state, wrRegData);
     input  [5:0] op, func;
    input  z, clock, resetn;
    output reg   wpc, wir, Inswmem, wreg,m2reg, wrRegData;
     output reg Datawmem;
    output reg [2:0] aluc;
    output reg [1:0]  pcsource, regrt;
    output reg  sext,alusrcb;
    output reg [2:0] state;
    parameter [2:0]  sif  = 3'b000, // IF  state
                 sid  = 3'b001, // ID  state
                 sexe = 3'b010, // EXE state
                 smem = 3'b011, // MEM state
                 swb  = 3'b100; // WB  state
    reg [2:0] next_state;
    wire i_add,i_addi,i_sub,i_ori,i_and,i_or,i_sll, i_slt, i_j, i_jr, i_jal, i_move,i_sw,i_lw,i_beq,i_halt;
    assign i_add    = (op[5:0] == 6'b000000) ? 1 : 0;
    assign i_sub   = (op[5:0] == 6'b000001) ? 1 : 0;
    assign i_addi    = (op[5:0] == 6'b000010) ? 1 : 0;
    assign i_or      = (op[5:0] == 6'b010000) ? 1 : 0;
    assign i_and    = (op[5:0] == 6'b010001) ? 1 : 0;
    assign i_ori       = (op[5:0] == 6'b010010) ? 1 : 0;
    assign i_sll     = (op[5:0] == 6'b011000) ? 1 : 0;
    assign i_move = (op[5:0] == 6'b100000) ? 1 : 0;
    assign i_slt     = (op[5:0] == 6'b100111) ? 1 : 0;
    assign i_sw      = (op[5:0] == 6'b110000) ? 1 : 0;
    assign i_lw       = (op[5:0] == 6'b110001) ? 1 : 0;
    assign i_beq    = (op[5:0] == 6'b110100) ? 1 : 0;
    assign i_j    = (op[5:0] == 6'b111000) ? 1 : 0;
    assign i_jr    = (op[5:0] == 6'b111001) ? 1 : 0;
    assign i_jal    = (op[5:0] == 6'b111010) ? 1 : 0;
    assign i_halt    = (op[5:0] == 6'b111111) ? 1 : 0;
    always @* begin      // control signals' default outputs:
    wpc =0;           // do not write pc 
        wir =0;           // do not write ir
        Inswmem =0;          // do not write memory
        Datawmem = 0;
        wreg =0;          // do not write register file 
       aluc = 4'bx000;   // ALU operation: add
       alusrcb = 2'h0;   // ALU input b: reg b
        regrt = 2'h0;         // reg dest no: rd
        m2reg =0;         // select reg c
        pcsource = 2'b00;  // select alu output
        sext = 1;         // sign extend
       wrRegData = 0;
        case (state) //---------------------------------------- IF:
            sif: begin       // IF state
               wpc = 0;
                wir =1;      // write IR    
                pcsource = 2'h0;
                Inswmem = 0;
                //alusrca = 1; //PC
                //alusrcb = 2'h1;  // 4
                next_state = sid;  // next state: ID
            end //--------------------------------------------- ID:   
            sid: begin              // ID state
                 if (i_j || i_jal || i_jr || i_halt) begin
                      next_state = sif;
                      if (i_j) begin
                          wir = 0;
                          wpc = 1;
                          pcsource = 2'h3;
                      end else if (i_jr) begin
                          pcsource = 2'h2;
                            wpc = 1;
                            wir = 0;
                            wreg = 0;
                      end  else if (i_jal) begin
                          wpc = 1;
                            pcsource = 2'h3;
                            wreg = 1;
                            wir = 0;
                            wrRegData = 0;
                            regrt = 2'h0;
                      end else if (i_halt) begin
                          wpc = 0;
                            wreg = 0;
                      end
                 end else if (i_add || i_sub || i_addi || i_and || i_or || i_ori || i_move || i_slt || i_sll || i_beq || i_sw || i_lw) begin
                      next_state = sexe;
                      wpc = 0;
                      wir = 0;
                      aluc = 3'h0;
                      alusrcb = 1;
                      sext = 1;
                     wreg = 0;
                 end

            end //--------------------------------------------- EXE:    
            sexe: begin                   // EXE state
             if (i_sll) begin
                     wir = 0;
                      alusrcb = 1;
                      aluc = 3'b100;
                      next_state = swb;
                 end else if (i_add || i_sub || i_and || i_or || i_move || i_slt) begin
                     wir = 0;
                      alusrcb = 0;
                      next_state = swb;
                      if (i_add || i_move) begin
                          aluc = 3'b000;
                      end else if (i_sub) begin
                          aluc = 3'b001;
                      end else if (i_and) begin
                          aluc = 3'b110;
                      end else if (i_slt) begin
                          aluc = 3'b010;
                      end else begin
                          aluc = 3'b101;
                      end
                 end else if (i_ori || i_addi) begin
                     wir = 0;
                      alusrcb = 1;
                      next_state = swb;
                     if (i_addi) begin
                            sext = 1;
                            aluc = 3'b000;
                      end else begin
                          sext = 0;
                            aluc = 3'b101;
                      end
                 end else if (i_beq) begin
                     wpc = 1;
                      wir = 0;
                      next_state = sif;
                      if (z)
                          pcsource = 2'b01;
                      else
                          pcsource = 2'b00;
                      aluc = 3'b001;
                      alusrcb = 0;
                 end else if (i_lw || i_sw) begin
                     sext = 1;
                      aluc = 3'b000;
                      alusrcb = 1;
                      next_state = smem;

                 end
            end //--------------------------------------------- MEM:
            smem: begin             // MEM state
                 if (i_sw) begin
                      Datawmem = 1;
                      wir = 0;
                      wpc = 1;
                      next_state = sif;
                 end else if (i_lw) begin
                     Datawmem = 0;
                      wir = 0;
                      next_state = swb;
                      m2reg = 1;
                    wrRegData = 1;
                 end
            end //--------------------------------------------- WB:
            swb: begin                    // WB state
                next_state = sif;
                 wpc = 1;
                 if (i_lw) begin
                     m2reg = 1;
                    wrRegData = 1;
                      regrt = 2'h1;
                     wreg = 1;
                      wir = 0;
                 end else if (i_addi || i_ori) begin
                     wreg = 1;
                      m2reg = 0;
                      wrRegData = 1;
                      regrt = 2'h1;
                      wir = 0;
                 end else if (i_add || i_sub || i_and || i_or || i_move || i_slt) begin
                     wreg = 1;
                      m2reg = 0;
                      wrRegData = 1;
                      regrt = 2'h2;
                  wir = 0;
                 end else if (i_sll) begin
                     wreg = 1;
                      m2reg = 0;
                      wrRegData = 1;
                      regrt = 2'h1;
                      wir = 0;
                 end
            end //--------------------------------------------- END
        endcase
   end
    always @ (posedge clock) begin
         if (resetn == 1) begin
              state <= sif;
         end else begin
              state <= next_state;
         end
    end
endmodule

regfile.v

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    15:17:50 05/12/2016 
// Design Name: 
// Module Name:    sc_regfile 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module sc_regfile(rs, rt, i_data, rd, we, clk, o_data_1, o_data_2
    );
  input [4:0] rs, rt, rd;
  input [31:0] i_data;
  input we, clk;
  output [31:0] o_data_1, o_data_2;
  reg [31:0] register [0:31];
  initial begin
    register[0] = 0;
  end
  assign o_data_1 = register[rs];
  assign o_data_2 = register[rt];
  always @(posedge clk) begin
    if ((rd != 0) && (we == 1)) begin
      register[rd] = i_data;
    end
  end
endmodule

imem.v

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    14:56:43 05/12/2016 
// Design Name: 
// Module Name:    sc_imem 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module sc_imem( addr, read_en_, instruction
    );
    input read_en_;
    input [31:0] addr;
    output reg [31:0] instruction;
    reg [7:0] mem [0:350];
    initial begin
        mem[251] = 8'b11100000;
          mem[250] = 8'b00000000;
          mem[249] = 8'b00000000;
          mem[248] = 8'b01000100;
          mem[275] = 8'b00001000;
          mem[274] = 8'b00000001;
          mem[273] = 8'b00000000;
          mem[272] = 8'b00110000;
          mem[279] = 8'b01001000;
          mem[278] = 8'b00000010;
          mem[277] = 8'b00000000;
          mem[276] = 8'b00000011;
          mem[283] = 8'b00000000;
          mem[282] = 8'b00100010;
          mem[281] = 8'b00011000;
          mem[280] = 8'b00000000;
          mem[287] = 8'h04;
          mem[286] = 8'h61;
          mem[285] = 8'h20;
          mem[284] = 8'h00;
          mem[291] = 8'h44;
          mem[290] = 8'h62;
          mem[289] = 8'h28;
          mem[288] = 8'h00;
          mem[295] = 8'h40;
          mem[294] = 8'h25;
          mem[293] = 8'h40;
          mem[292] = 8'h00;
          mem[299] = 8'h81;
          mem[298] = 8'h00;
          mem[297] = 8'h50;
          mem[296] = 8'h00;
          mem[303] = 8'he8;
          mem[302] = 8'h00;
          mem[301] = 8'h00;
          mem[300] = 8'h51;
          mem[307] = 8'h9c;
          mem[306] = 8'h22;
          mem[305] = 8'h30;
          mem[304] = 8'h00;
          mem[311] = 8'h9c;
          mem[310] = 8'h41;
          mem[309] = 8'h38;
          mem[308] = 8'h00;
          mem[315] = 8'h60;
          mem[314] = 8'h42;
          mem[313] = 8'h00;
          mem[312] = 8'h02;
          mem[319] = 8'hd0;
          mem[318] = 8'h22;
          mem[317] = 8'hff;
          mem[316] = 8'hfe;
          mem[323] = 8'hfc;
          mem[322] = 8'h00;
          mem[321] = 8'h00;
          mem[320] = 8'h00;
          mem[327] = 8'hc0;
          mem[326] = 8'h25;
          mem[325] = 8'h00;
          mem[324] = 8'h02;
          mem[331] = 8'hc4;
          mem[330] = 8'h2c;
          mem[329] = 8'h00;
          mem[328] = 8'h02;
          mem[335] = 8'he7;
          mem[334] = 8'he0;
          mem[333] = 8'h00;
          mem[332] = 8'h00;
        instruction = 0;
     end
     always @(addr or read_en_) begin               
            instruction[31:24] = mem[addr+3];
            instruction[23:16] = mem[addr+2];
         instruction[15:8] = mem[addr+1];
         instruction[7:0] = mem[addr];
    end

endmodule

signExtend.v

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    18:50:53 05/12/2016 
// Design Name: 
// Module Name:    sc_signExtend 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module sc_signExtend(i_num, extSel, o_num
    );
  input wire[15:0] i_num;
  input wire extSel;
  output reg[31:0] o_num;
  initial begin
    o_num = 0;
  end
  always @(i_num or extSel) begin
    if (extSel) begin
      o_num <= 16i_num[15], i_num[15:0];
    end else begin
        o_num <= 160, i_num[15:0];
     end
  end

endmodule

alu.v

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    14:25:48 05/12/2016 
// Design Name: 
// Module Name:    sc_alu 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module sc_alu(A, B, ALUOp, zero, result
    );
  input [31:0] A, B;
  input [2:0] ALUOp;
  output zero;
  output reg [31:0] result;
  initial begin
        result = 0;
  end
  assign zero = (result? 0 : 1);
  always @(A or B or ALUOp) begin
    case(ALUOp)
      3'b000: result = A + B;
      3'b001: result = A - B;
      3'b010: result = (B > A? 1: 0);
        3'b011: result = A>>B;
      3'b100: result = A<<B;
      3'b101: result = A | B;
      3'b110: result = A & B;
      3'b111: result = (~A & B) | (A & ~B);
      default: result = 0;
    endcase
  end

endmodule

pc.v

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    19:07:29 05/12/2016 
// Design Name: 
// Module Name:    sc_pc 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module sc_pc(clk, i_pc, pcWire, reset, o_pc, set_pc
    );
  input wire clk, pcWire, reset;
  input wire [31:0] i_pc;
  input wire [31:0]set_pc;
  output reg [31:0] o_pc;
  always @(posedge clk) begin
    if (reset) begin
      o_pc = set_pc;
    end else if (pcWire) begin
      o_pc = i_pc;
    end else if (!pcWire) begin //í£?ú
        o_pc = o_pc;
     end
  end

endmodule

datemen.v(时钟下降沿触发完美解决竞争冒险问题。。)

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    18:43:30 05/12/2016 
// Design Name: 
// Module Name:    sc_datemem 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module sc_datemem(clk, i_data, addr, rw, o_data
    );
    input [31:0] i_data;
    input [31:0] addr;
    input rw, clk;
    output reg [31:0] o_data;
    reg [7:0] memory [0:63];
     initial begin
        o_data = 0;
     end
    always @(negedge clk) begin 
      if (rw) begin
          memory[addr+3] = i_data[31:24];
          memory[addr+2] = i_data[23:16];
          memory[addr+1] = i_data[15:8];
          memory[addr] = i_data[7:0];
      end else begin
          o_data[31:24] = memory[addr+3];
          o_data[23:16] = memory[addr+2];
          o_data[15:8] = memory[addr+1];
          o_data[7:0] = memory[addr];
         end
    end
endmodule

pcaddFour.v

module sc_addfour(i_pc, o_pc
    );
  input wire [31:0] i_pc; 
  output wire [31:0] o_pc;
  assign o_pc[31:0] = i_pc[31:0] + 4;
endmodule

pcaddmin.v(pc+立即数的模块)

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    19:32:56 05/12/2016 
// Design Name: 
// Module Name:    sc_pcaddmin 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module sc_pcaddmin(now_pc, addNum, o_pc
    );
  input [31:0] now_pc, addNum;
  output [31:0] o_pc;
  assign o_pc = now_pc + (addNum * 4); 

endmodule

pcdirect.v(pc直接跳转地址)

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    19:35:07 05/12/2016 
// Design Name: 
// Module Name:    sc_pcdirect 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module sc_pcdirect(i_pc, addr, o_pc
    );
    input [31:0] i_pc;
     input [25:0] addr;
    output reg [31:0] o_pc;
      initial begin
         o_pc = 0;
    end
     always @(i_pc or addr) begin
         o_pc[31:28] = i_pc[31:28];
          o_pc[27:2] = addr[25:0];
          o_pc[1:0] = 2'b00;
     end
endmodule

dataselect.v ( 包含三个选择器)

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    19:14:04 05/12/2016 
// Design Name: 
// Module Name:    sc_dataselect 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module dataSelect_5_Bit(B, C, Ctrl, S);
  input [4:0] B, C;
  input [1:0]Ctrl;
  output reg [4:0] S;
  wire [4:0] A;
  assign A = 5'h1f;
  initial begin
        S = 0;
   end
  always @(*) begin
       if (Ctrl == 2'b00)
          S = A;
      else if (Ctrl == 2'b01)
          S = B;
      else
          S = C;
    end 
endmodule

module dataSelect_32_Bit(A, B, Ctrl, S);
  input [31:0] A, B;
  input Ctrl;
  output [31:0] S;
  assign S = (Ctrl == 1'b1 ? B : A);
endmodule

module dataSelect_32_Bit_reg(A, B, Ctrl, S);
  input [31:0] A, B;
  input Ctrl;
  output reg [31:0] S;
  always @(*) begin
       if (Ctrl == 1) begin
          S = A;
        end
      else begin
          S = B;
        end
    end 
endmodule

module dataSelect4_32_Bit(A, B, C, D, Ctrl, S);
  input [31:0] A, B, C, D;
  input [1:0]Ctrl;
  output reg [31:0] S;
  always @(*) begin
       if (Ctrl == 2'b00) begin
          S = A;
        end
      else if (Ctrl == 2'b01) begin
          S = B;
        end else if (Ctrl == 2'b10) begin
            S = C;
       end else begin
          S = D;
        end
    end 
endmodule

接下来是各个寄存器的代码
首先是IR.v

`timescale 1ns / 1ps
/////////////////////////////////////////////////////////P4-verilog实现mips单周期CPU

流水线cpu —Verilog HDL

P4 - Verilog单周期CPU

多周期CPU设计

Verilog如何检测一个时钟周期肿的翻转?

单周期CPU设计