How to break always block in Verilog?

Eng.Fouad picture Eng.Fouad · Mar 27, 2012 · Viewed 16.5k times · Source

I am trying to simulate a simple MIPS processor using behavior code in Verilog. I have finished writing the code but I reach to a final step where I want to break the always block after done with executing the MIPS instructions. Here is my code:

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

I tried $finish but it doesn't work:

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

So, how can I break the always block? or should I use something else instead?

Answer

Ross Rogers picture Ross Rogers · Mar 27, 2012

always isn't a while loop. See wikipedia's entry on verilog. Since you don't have any temporal consuming statements like #10 it will continuously execute your code as in an accidental while 1 block in C. Either that, or the compiler might simply flag your code as an error. However, using #10 in your code is just a hack. You really want to make your always block only execute every posedge clk or create a proper pipline. So, you'll need an enable signal and you need to make your always block be @(posedge clk) to schedule the block to happen every clock tick instead of forever, with no advancing of simulation time.