Как разбить всегда блок в Verilog? - PullRequest
4 голосов
/ 27 марта 2012

Я пытаюсь смоделировать простой процессор MIPS, используя код поведения в Verilog. Я закончил писать код, но дошел до последнего шага, где я хочу разорвать блок Always после выполнения инструкций MIPS. Вот мой код:

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? или я должен использовать что-то другое вместо этого?

Ответы [ 2 ]

3 голосов
/ 28 марта 2012

always не является циклом while.См. запись в Википедии на Verilog .Поскольку у вас нет временных операторов, таких как #10, он будет постоянно выполнять ваш код как случайный блок while 1 в C. Либо это, либо компилятор может просто пометить ваш код как ошибку.Тем не менее, использование #10 в вашем коде - просто взлом.Вы действительно хотите, чтобы ваш always блок выполнялся только каждый posedge clk или создавал надлежащий трубопровод.Таким образом, вам понадобится сигнал включения, и вы должны сделать так, чтобы ваш блок всегда был @(posedge clk), чтобы планировать, что блок будет происходить каждый такт, а не навсегда, без увеличения времени моделирования.

1 голос
/ 28 марта 2012

Можно ли использовать регистр для управления блоком всегда с помощью оператора if?

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

Отключение приводит к разрыву оператора begin, помеченного как loop_block, а флаг enabled предотвращает повторный вход.

...