2012-03-27 69 views
4

我試圖模擬一個簡單的MIPS處理器在Verilog中使用行爲代碼。我已經完成了編寫代碼的工作,但是我已經完成了最後一步,在完成執行MIPS指令後,我想打破always塊。這裏是我的代碼:如何在Verilog中始終阻止?

module MIPS_Processor(output reg[7:0] LEDs, input[7:0] Switches); 
    reg [31:0] memory[0:4095]; // 4K memory cells that are 8 bits wide 
    reg [31:0] code[0:1023];  // 1K memory cells that are 8 bits wide 
    reg [31:0] registers[0:31]; // 32 registers that are 32 bits wide 
    reg [31:0] PC;    // The program counter 

    reg [31:0] instruction; 
    reg [5 :0] op; 
    reg [4 :0] rs; 
    reg [4 :0] rt; 
    reg [4 :0] rd; 
    reg [4 :0] shamt; 
    reg [5 :0] funct; 
    reg signed [15:0] immediate_offset; 
    reg [25:0] target; 

    reg [1:0] instruction_type; // 00 --> R | 01 --> I | 10 --> J | 11 --> EXTRA 

    reg [31:0] rs_value; 
    reg [31:0] rt_value; 
    reg [31:0] rd_value; 

    reg done = 0; 

    /* 
     Here we insert the code in the code array 
    */ 

    initial 
     begin 
      PC = 0; 
     end 

    always 
     begin 
      // 1. Fetch an instruction from memory 
      instruction = code[PC]; 

      // 2. Increment the program counter register (by the instruction length) 
      PC = PC + 1; 

      // 3. Decode the instruction 
      /* 
       The instructions are: 
              6 5 5 5 5 6 
              _____________________________ 
       or rd, rs, rt   | 0 | rs | rt | rd | 0 | 0x25 | 

              6 5 5  16 
              _____________________________ 
       ori rt, rs, immediate | 0xd | rs | rt | immediate | 

              6 5 5 5 5 6 
              _____________________________ 
       and rd, rs, rt   | 0 | rs | rt | rd | 0 | 0x24 | 

              6 5 5  16 
              _____________________________ 
       andi rt, rs, immediate | 0xc | rs | rt | immediate | 

              6 5 5   16 
              _____________________________ 
       beq rs, rt, offset  | 4 | rs | rt | offset  | 

              6 5 5 5 5 6 
              _____________________________ 
       sub rd, rs, rt   | 0 | rs | rt | rd | 0 | 0x22 | 

              6 5 5 5 5 6 
              _____________________________ 
       add rd, rs, rt   | 0 | rs | rt | rd | 0 | 0x20 | 

              6 5 5  16 
              _____________________________ 
       addi rt, rs, immediate | 8 | rs | rt | immediate | 

              6    26 
              _____________________________ 
       j target    | 2 |   target   | 

              6 5 5 5 5 6 
              _____________________________ 
       slt rd, rs, rt   | 0 | rs | rt | rd | 0 | 0x2a | 

              6  5 5  16 
              _____________________________ 
       lw rt, rs[offset]  | 0x23 | rs | rt | offset | 

              6  5 5  16 
              _____________________________ 
       sw rt, rs[offset]  | 0x2b | rs | rt | offset | 


       ::EXTRA INSTRUCTIONS:: 

              6 5   21 
              _____________________________ 
       input rs     | 4 | rs |  0   | 

              6 5   21 
              _____________________________ 
       output rs     | 4 | rs |  1   | 

      */ 
      op[5:0] = instruction[31:26]; 
      case(op) 
       0: /* R-type */ 
        begin 
         rs = instruction[25:21]; 
         rt = instruction[20:16]; 
         rd = instruction[15:11]; 
         shamt = instruction[10:6]; 
         funct = instruction[5:0]; 
         instruction_type = 2'b00; 
        end 

       1: /* END OF CODE */ 
        begin 
         //$finish; 
        end 

       2: /* J-type */ 
        begin 
         target = instruction[25:0]; 
         instruction_type = 2'b10; 
        end 

       4: /* EXTRA */ 
        begin 
         rs = instruction[25:21]; 
         funct = instruction[20:0]; 
         instruction_type = 2'b11; 
        end 

       default: /* I-type */ 
        begin 
         rs = instruction[25:21]; 
         rt = instruction[20:16]; 
         immediate_offset = instruction[15:0]; 
         instruction_type = 2'b01; 
        end 
      endcase 


      // 4. Fetch operands, if any, usually from registers 
      case(instruction_type) 
       2'b00: /* R-type */ 
        begin 
         rs_value = registers[rs]; 
         rt_value = registers[rt]; 
        end 

       2'b01: /* I-type */ 
        begin 
         rs_value = registers[rs]; 
        end 
       2'b11: /* EXTRA */ 
        begin 
         if(funct == 1) rs_value = registers[rs]; 
        end 
      endcase 

      // 5. Perform the operation 
      case(instruction_type) 
       2'b00: /* R-type */ 
        begin 
         case(funct) 
          2'h20: /* add rd, rs, rt */ 
           begin 
            rd_value = rs_value + rt_value; 
           end 
          2'h22: /* sub rd, rs, rt */ 
           begin 
            rd_value = rs_value - rt_value; 
           end 
          2'h24: /* and rd, rs, rt */ 
           begin 
            rd_value = rs_value & rt_value; 
           end 
          2'h25: /* or rd, rs, rt */ 
           begin 
            rd_value = rs_value | rt_value; 
           end 
          2'h2a: /* slt rd, rs, rt */ 
           begin 
            rd_value = rs_value < rt_value? 1 : 0; 
           end 
         endcase 
        end 

       2'b01: /* I-type */ 
        begin 
         case(op) 
          4: /* beq rs, rt, offset */ 
           begin 
            if(rs_value < rt_value) PC = immediate_offset; 
           end 
          8: /* addi rt, rs, immediate */ 
           begin 
            rt_value = rs_value + immediate_offset; 
           end 
          1'hc: /* andi rt, rs, immediate */ 
           begin 
            rt_value = rs_value & immediate_offset; 
           end 
          1'hd: /* ori rt, rs, immediate */ 
           begin 
            rt_value = rs_value | immediate_offset; 
           end 
          2'h23: /* lw rt, rs[offset] */ 
           begin 
            rt_value = memory[rs + immediate_offset]; 
           end 
          2'h2b: /* sw rt, rs[offset] */ 
           begin 
            memory[rs + immediate_offset] = rt_value; 
           end 
         endcase 
        end 

       2'b10: /* J-type */ 
        begin 
         case(op) 
          2: /* j target */ 
           begin 
            PC = target; 
           end 
         endcase 
        end 

       2'b11: /* EXTRA */ 
        begin 
         case(funct) 
          0: /* input rs */ 
           begin 
            rs_value[7:0] = Switches; 
           end 

          1: /* output rs */ 
           begin 
            LEDs = rs_value[7:0]; 
           end 
         endcase 
         if(funct == 1) rs_value = registers[rs]; 
        end 
      endcase 

      // 6. Store the results 
      case(instruction_type) 
       2'b00: /* R-type */ 
        begin 
         registers[rd] = rd_value; 
        end 
       2'b01: /* I-type */ 
        begin 
         case(op) 
          8: /* addi rt, rs, immediate */ 
           begin 
            registers[rt] = rt_value; 
           end 
          1'hc: /* andi rt, rs, immediate */ 
           begin 
            registers[rt] = rt_value; 
           end 
          1'hd: /* ori rt, rs, immediate */ 
           begin 
            registers[rt] = rt_value; 
           end 
          2'h23: /* lw rt, rs[offset] */ 
           begin 
            registers[rt] = rt_value; 
           end 
         endcase 
        end 
       2'b11: /* EXTRA */ 
        begin 
         if(funct == 0) registers[rs] = rs_value; 
        end 
      endcase 

     end 
endmodule 

我試過$結束,但它不工作:

1: /* END OF CODE */ 
    begin 
     //$finish; 
    end 

所以,我怎樣才能打破always塊?還是應該使用別的東西呢?

回答

1

你可以使用寄存器來控制if語句的always塊嗎?

always begin : loop_block 
    if(enabled) begin 
     ... 
     if (nothing_left_to_do) begin 
      enabled = 0; 
      disable loop_block; 
     end 
     ... 
    end else begin 
     #1000 //delay to prevent infinite execution of block 
    end 
end //loop_block 

的禁用導致標記爲「loop_block」打破了開始的語句,並啓用的標誌可防止折返。

+0

'禁用loop_block;'工作得很好。謝謝+1 :) – 2012-03-27 20:32:59

3

always不是while循環。見wikipedia's entry on verilog。由於您沒有像#10這樣的暫時消耗語句,它會連續執行您的代碼,如C中意外的while 1塊所示。或者,編譯器可能會簡單地將您的代碼標記爲錯誤。但是,在代碼中使用#10只是一種破解。你真的想讓你的always塊只執行每個posedge clk或創建一個合適的管道。所以,你需要一個使能信號,並且你需要讓你的始終阻止爲@(posedge clk)來安排每個時鐘週期發生的時間塊,而不是永遠的,沒有模擬時間的提前。

+0

+1感謝提示:) – 2012-03-27 20:33:14

+0

此代碼不應該導致錯誤。只需要always關鍵字後面跟着一個語句。 – 2012-03-27 22:39:13

+0

Adam,我同意_syntactically_這可能在Verilog的語法中是合法的,但編譯器也可以有語義檢查。特別是如果編譯器看到一個直線[「基本塊」](http://en.wikipedia.org/wiki/Basic_block),它自身循環,沒有其他圖形弧到不同的基本塊或子圖的子圖基本塊具有相同的屬性。 – 2012-03-27 23:38:38