2012-03-27 10 views
4

Verilogのビヘイビアコードを使って簡単なMIPSプロセッサをシミュレートしようとしています。私はコードを書き終えましたが、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

'disable loop_block;'はうまく動作します。ありがとう+1: –

3

alwaysは、whileループではありません。 wikipedia's entry on verilogを参照してください。 #10のような一時的な文がないので、Cの偶発的なwhile 1ブロックのようにあなたのコードを継続して実行します。それとも、コンパイラがあなたのコードにエラーとして単にフラグを立てるかもしれません。しかし、あなたのコードに#10を使用するだけでハックです。 alwaysブロックはすべてposedge clkを実行するか、適切なpiplineを作成するだけです。したがって、イネーブル信号が必要になります。また、常にブロックすることを@(posedge clk)にする必要があります。シミュレーション時間が進まずにブロックを永遠にではなくクロックチックごとにスケジュールする必要があります。

+0

+1ヒントのためにありがとう:) –

+0

このコードはエラーを引き起こしてはいけません。 alwaysキーワードの後に​​は必ずステートメントが必要です。 –

+0

アダム、私は_syntactically_これはVerilogの文法で合法かもしれないことに同意しますが、コンパイラはセマンティックチェックも持つことができます。特に、コンパイラが、別のグラフアークを持たずに別の基本ブロックまたはそのサブグラフにループバックする直線["Basic Block"](http://en.wikipedia.org/wiki/Basic_block)基本ブロックは同じ性質を有する。 –

関連する問題