试图编写单循环verilog代码?

时间:2015-02-10 15:32:10

标签: verilog

我正在尝试编写一个单循环mips verilog代码,其中只包含选定的指令,通过一个简单的测试,我花了两天时间编写下面的代码,但我检查了每条指令的指令但是进入分支(第一分支)指令我真的变得绝望了(新的pc值没有正确更新)。我会非常感谢你的任何建议。

PS:正确执行第一个分支之前的指令。

这是主要代码

`timescale 1ns/10ps
// R Format funcs
`define ADDU 6'b100001
`define ADD 6'b100000
`define SUB 6'b100011
`define AND 6'b100100
`define XOR 6'b100110
`define NOR 6'b100111
`define SLT 6'b101010
`define MULT 6'b011000
`define SLTU 6'b101011
`define MULTU 6'b011001
`define JALR 6'b001001
`define JR 6'b001000
`define MFHI 6'b010000
`define MFLO 6'b010010

// I & J Format op
`define ADDI 6'b001000
`define ADDIU 6'b001001
`define ORI 6'b001101
`define XORI 6'b001110
`define ANDI 6'b001100
`define SLTI 6'b001010
`define SLTIU 6'b001011
`define LUI 6'b001111
`define LW 6'b100011
`define SW 6'b101011
`define BEQ 6'b000100
`define BNE 6'b000101
`define J 6'b000010
`define JAL 6'b000011

// ALU OP
`define alu_add 4'b0000
`define alu_sub 4'b0001
`define alu_and 4'b0010
`define alu_or 4'b0011
`define alu_xor 4'b0100
`define alu_nor 4'b0101
`define alu_sltu 4'b0110
`define alu_slt 4'b0111
`define alu_addu 4'b1000




module single_cycle_mips(

   input clk,
   input reset 
);

   wire alu_z;
   reg [3:0] alu_op;
   reg [1:0] aluSrcB ,RegDst ;
   reg [2:0] WD_e;
   reg [4:0] Regno , flag=0;
   reg aluSrcA, SE_ZEn, rf_wrt;
   reg pc_wrt, ir_wrt, IorD, mar_wrt ,mult_s ,is_s,mem_wrt;


   wire [31:0] rf_rd_1, rf_rd_2, alu_result ,s1,s2,mem_addr,mem_write_data,mem_read_data;
   reg [31:0] pc, MemtoReg, ir,mar, aluB , aluA ,A ,B ,HI ,LO;


   // CONTROLLER Starts Here



   wire [5:0] ir_op = ir[31:26];
   wire [5:0] funct = ir[5:0];


   always @(ir) begin : MAIN

      //nxt_state = 'bx;

      alu_op  = 'bx; aluSrcB = 'bx; aluSrcA = 'bx; SE_ZEn = 'bx;
      rf_wrt = 1'b0; pc_wrt = 1'b0; ir_wrt = 1'b0; WD_e = 'bx;
      mem_wrt = 1'b0; mult_s = 'bx; mar_wrt = 1'b0; Regno = 'bx;
      is_s = 'bx; RegDst = 'bx ;


            IorD = 0;
            ir_wrt = 1'b1;    // load IR by memory data
            //aluSrcA = 1'b0;      //
            //aluSrcB = 2'b01;      //
            //alu_op = `alu_addu;    //
            //pc_wrt = 1'b1;    // pc <- pc + 4
            pc = pc + 4;
         #8


            case(ir_op)
               6'b000000:begin             // R-format
                  if(funct == `MFHI) begin                
                    WD_e = 3'b010;
                    rf_wrt = 1'b1;
                    RegDst = 2'b01;
                    //nxt_state = FETCH1;
                    end
                  else if(funct == `MFHI) begin               
                    WD_e = 3'b011;
                    rf_wrt = 1'b1;
                    RegDst = 2'b01;
                    //nxt_state = FETCH1;
                    end
                  else if((funct == `JALR) || (funct== `JR)) begin
                    A =rf_rd_1;
                    if(funct == `JALR) begin
                    rf_wrt = 1'b1;
                    WD_e = 3'b100;
                    RegDst = 2'b01;
                    end
                    pc = A;
                    end
                  else begin
                  A = rf_rd_1;
                  B = rf_rd_2;
                   #3
                  rf_wrt = 1'b1;
                  aluSrcA = 1'b1;
                  aluSrcB = 2'b00;
                  WD_e = 3'b001;
                  RegDst = 2'b01;

        case(funct[5:0]) 
                    `ADD: begin alu_op = `alu_add; end 
                    `ADDU: begin alu_op = `alu_addu; end
                    `SUB: begin alu_op = `alu_sub;   end 
                    `AND: begin alu_op = `alu_and;   end 
                    `XOR: begin alu_op = `alu_xor;   end 
                    `NOR: begin alu_op = `alu_nor;  end 
                    `SLTU: begin alu_op = `alu_sltu;  end 
                    `SLT: begin alu_op = `alu_slt;   end 
                    `MULT: begin 
                        if(flag <=18 && flag!=0)
                        flag= flag+1;
                        else if(flag == 18) begin
                        HI <= #0.1 s2;
                        LO <= #0.1 s1;
                        flag = 0;
                        end
                        else if(flag==0) begin
                        mult_s = 1'b1;
                        is_s = 1'b1;
                        end
                        end
                    `MULTU: begin
                        if(flag <=18 && flag!=0)
                        flag= flag+1;
                        else if(flag == 18) begin
                        HI <= #0.1 s2;
                        LO <= #0.1 s1;
                        flag = 0;
                        //nxt_state = FETCH1;
                        end
                        else if(flag==0) begin
                        mult_s = 1'b1;
                        is_s = 1'b1;
                        end
                        end

        endcase

                  end
                  end
               `ADDI ,`ADDIU ,`ORI ,`XORI ,`ANDI ,`SLTI, `SLTIU: // I format
                    begin
            A = rf_rd_1;
            #3
            rf_wrt = 1'b1;
            aluSrcA = 1'b1;
            aluSrcB = 2'b10;
            WD_e = 3'b001;
            RegDst = 2'b00;
            case(ir_op)
                `ADDI:begin
            SE_ZEn =1'b1;   
            alu_op = `alu_add;
            //nxt_state = FETCH1;
                end
                `ADDIU:begin
            SE_ZEn =1'b0;   
            alu_op = `alu_addu;
            //nxt_state = FETCH1;
                end
                `ANDI:begin
            SE_ZEn =1'b1;
            alu_op = `alu_and;
            //nxt_state = FETCH1;
                end     
                `ORI:begin
            SE_ZEn =1'b0;
            alu_op = `alu_or;
            //nxt_state = FETCH1;
                end     
                `XORI:begin
            SE_ZEn =1'b0;
            alu_op = `alu_xor;
            //nxt_state = FETCH1;
                end     
                `SLTI:begin
            SE_ZEn =1'b1;
            alu_op = `alu_slt;
            //nxt_state = FETCH1;
                end 
                `SLTIU:begin
            SE_ZEn =1'b0;
            alu_op = `alu_sltu;
            //nxt_state = FETCH1;
                end 
        endcase
                    end 
                `LUI: begin
                    WD_e = 3'b101;
                    rf_wrt = 1'b1;
                    RegDst = 2'b00;
                    end
                `LW: begin
            A = rf_rd_1;
            mar_wrt = 1'b1;
            aluSrcA = 2'b1;
            aluSrcB = 2'b10;            
            SE_ZEn = 1;
            alu_op = `alu_add;
            #3
            IorD = 1;
            #8
            rf_wrt = 1'b1;
            WD_e = 3'b000;
            RegDst = 2'b00;
            //nxt_state = FETCH1;
                    end
                `SW: begin
            A = rf_rd_1;
            B = rf_rd_2;
            mar_wrt = 1'b1;
            aluSrcA = 1'b1;
            aluSrcB = 2'b10;            
            SE_ZEn =1'b1;
            alu_op = `alu_add;
            #3
            IorD = 1;
            ir_wrt = 0;
            mem_wrt = 1;
            #4 begin IorD = 0; mem_wrt = 0; ir_wrt = 1; end
            //disable MAIN;

            //nxt_state = FETCH1;
                    end
                `BEQ ,`BNE: begin
            A = rf_rd_1;
            B = rf_rd_2;
            aluSrcA = 1'b1;
            aluSrcB = 2'b00;
            alu_op = `alu_xor;
            #3
            if( ((alu_z == 0) && ((ir_op)== `BEQ) ) || ((alu_z == 1) && ((ir_op)== `BNE)))
            disable MAIN;
            //nxt_state = FETCH1;
            else
            begin
            SE_ZEn =1'b1;
            aluSrcA = 1'b0;
            aluSrcB = 2'b11;
            alu_op = `alu_add;
            pc_wrt = 1'b1;
            //nxt_state = FETCH1;
            end
                  end   
                `J: begin
                    pc = {7'b00000,ir[25:0]};
                    //nxt_state = FETCH1;
                    end
                `JAL: begin
                    rf_wrt = 1'b1;
                    RegDst = 2'b10;
                    WD_e = 3'b100;
                    pc = {7'b00000,ir[25:0]};
                    //nxt_state = FETCH1;
                   end
             endcase



   end

   // CONTROLLER Ends Here

   // DATA PATH Starts Here

   always @(posedge clk)
      if(reset) begin
         pc <= #0.1 32'h00000000;
         IorD = 0;
         ir_wrt = 1'b1;
         end
      else if(pc_wrt)
         pc <= #0.1 alu_result;

   always @(posedge clk) if(ir_wrt)  ir <=  #0.1 mem_read_data;

   always @* if(mar_wrt) mar <= #0.1 alu_result;

   assign mem_write_data = B;

   assign mem_addr = IorD ? mar : pc;



   wire [31:0] SZout = SE_ZEn ? {{16{ir[15]}}, ir[15:0]} : {16'h0000, ir[15:0]};


   always @(*) begin
      case (aluSrcB)
         2'b00: aluB <= B;
         2'b01: aluB <= 32'h4;
         2'b10: aluB <= SZout;
         2'b11: aluB <= SZout << 2;
      endcase
      case (aluSrcA)
         1'b0: aluA = pc;
         1'b1: aluA = A;

      endcase
      case(RegDst)
        2'b00: Regno <= ir[20:16];
        2'b01: Regno <= ir[15:11];
        2'b10: Regno <= 31;
        endcase
      case(WD_e)
        3'b000: MemtoReg <= mem_read_data;
        3'b001: MemtoReg <= alu_result;
        3'b010: MemtoReg <= HI;
        3'b011: MemtoReg <= LO;
        3'b100: MemtoReg <= pc;
        3'b101: MemtoReg <= {ir[15:0],16'h0000};
        endcase

end   

    my_alu alu(
      .aluA(aluA),
      .aluB(aluB),
      .aluOp(alu_op),

      .aluResult(alu_result),
      .aluZero(alu_z));

    reg_file registers(
   .clk(clk),
   .write(rf_wrt),
   .WR(Regno),
   .WD(MemtoReg),
   .RR1(ir[25:21]),
   .RR2(ir[20:16]),
   .RD1(rf_rd_1),
   .RD2(rf_rd_2));   

    async_mem mem(
    .clk(clk),
    .write(mem_wrt),
    .address(mem_addr),
   .write_data(mem_write_data),
   .read_data(mem_read_data));



 multiplier u1( 
.clk(clk),
.start(mult_s),
.is_signed(is_s),
.a(A),
.b(B),
.s1(s1),
.s2(s2));

   // DATA PATH Ends Here



endmodule

module my_alu(
   input [31:0] aluA,
   input [31:0] aluB,
   input [ 3:0] aluOp,
   output reg[31:0] aluResult,
   output        aluZero
);

   always @(*)
      case(aluOp)
         `alu_add : aluResult <= #2 aluA + aluB;//begin if( aluA[31] == aluB[31]) aluResult <= #2 aluA + aluB;
                    //else  aluResult <= #2 aluA[31] ? ~aluA + aluB + 1'b1 : aluA + ~aluB +1'b1; end          // add
         `alu_addu : aluResult <= #2 aluA + aluB;
         `alu_sub : aluResult <= #2 aluA + ~aluB + 1'b1;      // sub
         `alu_and : aluResult <= #2 aluA & aluB;
         `alu_or  : aluResult <= #2 aluA | aluB;
         `alu_nor : aluResult <= #2 ~(aluA | aluB);    // ?? ~ ( aluA | aluB )
         `alu_xor : aluResult <= #2 aluA ^ aluB;
         `alu_sltu : aluResult <= #2 aluA < aluB ? 1 : 32'h00000000;
         `alu_slt: begin
            if( aluA[31]!=aluB[31])begin 
            if( aluA[31]== 1)
            aluResult <= #2 1;
            else if( aluA[31]== 0)
            aluResult <= #2 32'h00000000;
            end
            else if( aluA[31]==aluB[31] ) begin
            if (aluA[31]== 0)
            aluResult <= #2 aluA < aluB ? 1 : 32'h00000000;
            else if( aluA[31]== 1)
            aluResult <= #2 (~aluA+1'b1) < (~aluB+1'b1) ? 1 : 32'h00000000;
         end
         end
      endcase

   assign aluZero = ~ (|aluResult);

endmodule


module async_mem(
   input clk,
   input write,
   input [31:0] address,
   input [31:0] write_data,
   output [31:0] read_data
);


   reg [31:0] mem_data [0:1023];

   assign #7 read_data = mem_data[ address[31:2] ];

   always @(*)
      if(write)
         mem_data[ address[31:2] ] <= #2 write_data;

endmodule

   module reg_file(
   input clk,
   input write,
   input [4:0] WR,
   input [31:0] WD,
   input [4:0] RR1,
   input [4:0] RR2,
   output [31:0] RD1,
   output [31:0] RD2
);

   reg [31:0] rf_data [0:31];

   assign #2 RD1 = rf_data[ RR1 ];

   assign #2 RD2 = rf_data[ RR2 ];

   always @(*) begin
      if(write) begin
         rf_data[ WR ] <= #0.1 WD;

         `ifdef DEBUG
         if(WR)
            $display("$%0d = %x", WR, WD);
         `endif

      end
      rf_data[0] <= #0.1 32'h00000000;
   end

endmodule 

,这是测试代码的十六进制:

[0x000000]  0x34080000  # ori $t0, $zero, 0 ($t0 = $zero | 0)
[0x000004]  0x24090060  # addiu $t1, $zero, 96 ($t1 = 96)
[0x000008]  0x3403DEAD  # ori $v1, $zero, -8531 ($v1 = $zero | -8531)
[0x00000C]  0xAD030080  # sw $v1, 128($t0) (mem[$t0 + 128] = $v1)
[0x000010]  0x2129FFFF  # addi $t1, $t1, -1 ($t1 = $t1 + -1)
[0x000014]  0x25080004  # addiu $t0, $t0, 4 ($t0 = $t0 + 4)
[0x000018]  0x00631020  # add $v0, $v1, $v1 ($v0 = $v1 + $v1)
[0x00001C]  0x00621026  # xor $v0, $v1, $v0 ($v0 = $v1 ^ $v0)
[0x000020]  0x3843BEEF  # xori $v1, $v0, -16657 ($v1 = $v0 ^ -16657)
[0x000024]  0x1409FFF9  # bne $t1, $zero, -7 (if ($t1 != $zero) goto -7)
[0x000028]  0x20080004  # addi $t0, $zero, 4 ($t0 = 4)
[0x00002C]  0x20090060  # addi $t1, $zero, 96 ($t1 = 96)
[0x000030]  0x01294821  # addu $t1, $t1, $t1 ($t1 = $t1 + $t1)
[0x000034]  0x01294821  # addu $t1, $t1, $t1 ($t1 = $t1 + $t1)
[0x000038]  0x0109502A  # slt $t2, $t0, $t1 (if ($t0 < $t1) $t2 = 1 else $t2 = 0)
[0x00003C]  0x1140000E  # beq $t2, $zero, 14 (if ($t2 == $zero) goto 14)
[0x000040]  0x00085820  # add $t3, $zero, $t0 ($t3 = $t0)
[0x000044]  0x8D0C0080  # lw $t4, 128($t0) ($t4 = mem[$t0 + 128])
[0x000048]  0x000B502A  # slt $t2, $zero, $t3 (if ($zero < $t3) $t2 = 1 else $t2 = 0)
[0x00004C]  0x11400007  # beq $t2, $zero, 7 (if ($t2 == $zero) goto 7)
[0x000050]  0x216DFFFC  # addi $t5, $t3, -4 ($t5 = $t3 + -4)
[0x000054]  0x8DAE0080  # lw $t6, 128($t5) ($t6 = mem[$t5 + 128])
[0x000058]  0x01CC502B  # sltu $t2, $t6, $t4 (if ($t6 < $t4) $t2 = 1 else $t2 = 0)
[0x00005C]  0x11400003  # beq $t2, $zero, 3 (if ($t2 == $zero) goto 3)
[0x000060]  0xAD6E0080  # sw $t6, 128($t3) (mem[$t3 + 128] = $t6)
[0x000064]  0x000D5820  # add $t3, $zero, $t5 ($t3 = $t5)
[0x000068]  0x1000FFF7  # beq $zero, $zero, -9 (if ($zero == $zero) goto -9)
[0x00006C]  0xAD6C0080  # sw $t4, 128($t3) (mem[$t3 + 128] = $t4)
[0x000070]  0x21080004  # addi $t0, $t0, 4 ($t0 = $t0 + 4)
[0x000074]  0x1000FFF0  # beq $zero, $zero, -16 (if ($zero == $zero) goto -16)
[0x000078]  0x1000FFFF  # beq $zero, $zero, -1 (if ($zero == $zero) goto -1)

这是测试平台:

`timescale 1ns/1ns

module multi_cycle_mips__tb;

    reg clk = 1;
    always @(clk)
        clk <= #20 ~clk; //20

    reg reset;
    initial begin
        reset = 1;
        @(posedge clk);
        @(posedge clk);
        @(posedge clk);
        #1;
        reset = 0;
    end

    initial
        $readmemh("isort32.hex", uut.mem.mem_data);

    parameter end_pc = 32'h7C;

    integer i;
    always @(uut.pc)
        if(uut.pc == end_pc) begin
            for(i=0; i<96; i=i+1) begin
                $write("%x ", uut.mem.mem_data[32+i]);
                if(((i+1) % 16) == 0)
                    $write("\n");
            end
            $stop;
        end

    single_cycle_mips uut(
        .clk(clk),
        .reset(reset)
    );


endmodule 

0 个答案:

没有答案