Question

I am trying to simulate a simple MIPS processor on an FPGA using Verilog. 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 32 bits wide
    reg [31:0] code[0:1023];     // 1K memory cells that are 32 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;

    initial
        begin
            PC = 0;

            /* Here we insert the code in the code array */
            code[0] = 32'b00010010000000000000000000000000; // start : input  s0   # read switches.
            code[1] = 32'b00010010000000000000000000000001; //         output s0   # write leds.
            code[2] = 32'b00001000000000000000000000000000; //         j      start
            code[3] = 32'b00000100000000000000000000000000; // END OF CODE
        end

    always
        begin : loop_block
            // 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
                        disable loop_block;
                    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

            #100; /* Delay */

        end
endmodule

I have attched output reg[7:0] LEDs to 8 LEDs on the FPGA device, and input[7:0] Switches on 8 switches of the FPGA. The code is compiled without any error. But unfortunately, it doesn't work. The LEDs should show the states of the switches, but they are always turned off.

However, when I tried hardcode the LEDs states like LEDs[7:0] = 8'b11111111; inside the initial block, the LEDs stays turned on all the time. While when I placed LEDs[7:0] = 8'b11111111; inside the always block, the LEDs stays turned off all the time. It seems that the FPGA does not execute the code inside always block, what is wrong? Am I implementing the design in a wrong way?

Was it helpful?

Solution

You may be able to simulate this code with a Verilog simulator but you will not be able to synthesize this code and load it onto an FPGA. As the comments say, synthesizable Verilog code for FPGAs would have a clock. It should have constructs that look like this

always @* begin : combinational_logic
    //...
end

always @(posedge clk) begin : sequential_logic
    //...
end

OTHER TIPS

The contents of your code array also look wrong. The array dissassembles as:

BEQ     $16, $0, 0x4
BEQ     $16, $0, 0x8
J       0x0
BLTZ    $0, 0x4
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top