OpenCores
URL https://opencores.org/ocsvn/t6507lp/t6507lp/trunk

Subversion Repositories t6507lp

[/] [t6507lp/] [trunk/] [rtl/] [verilog/] [t6507lp_fsm.v] - Diff between revs 63 and 68

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 63 Rev 68
Line 46... Line 46...
////                                                                    ////
////                                                                    ////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
 
 
`timescale 1ns / 1ps
`timescale 1ns / 1ps
 
 
module t6507lp_fsm(clk_in, n_rst_in, alu_result, alu_status, data_in, address, control, data_out, alu_opcode, alu_a);
module t6507lp_fsm(clk_in, rst_in_n, alu_result, alu_status, data_in, address, control, data_out, alu_opcode, alu_a, alu_enable);
 
 
 
        parameter DATA_SIZE = 4'd8;
 
        parameter ADDR_SIZE = 4'd13;
 
 
        input clk_in;
        input clk_in;
        input n_rst_in;
        input rst_in_n;
        input [7:0] alu_result;
        input [DATA_SIZE-1:0] alu_result;
        input [7:0] alu_status;
        input [DATA_SIZE-1:0] alu_status;
        input [7:0] data_in;
        input [DATA_SIZE-1:0] data_in;
        output reg [12:0] address;
        output reg [ADDR_SIZE-1:0] address;
        output reg control; // one bit is enough? read = 0, write = 1
        output reg control; // one bit is enough? read = 0, write = 1
        output reg [7:0] data_out;
        output reg [DATA_SIZE-1:0] data_out;
        output reg [7:0] alu_opcode;
        output reg [DATA_SIZE-1:0] alu_opcode;
        output reg [7:0] alu_a;
        output reg [DATA_SIZE-1:0] alu_a;
 
        output reg alu_enable;
 
 
 
 
        // FSM states
        // FSM states
 
        localparam RESET = 4'b1111;
        localparam FETCH_OP = 4'b0000;
        localparam FETCH_OP = 4'b0000;
        localparam FETCH_LOW = 4'b0001;
        localparam FETCH_OP_CALC = 4'b0001;
        localparam FETCH_HIGH = 4'b0010;
        localparam FETCH_LOW = 4'b0010;
        localparam SET_PC = 4'b0011;
        localparam FETCH_HIGH = 4'b0011;
        localparam READ_EFFECTIVE = 4'b0100;
 
        localparam DO_OPERATION = 4'b0101;
 
        localparam WRITE_DUMMY = 4'b0110;
 
        localparam WRITE_EFFECTIVE = 4'b0111;
 
        localparam CALCULATE_INDEX = 4'b1000;
 
        localparam CHECK_FOR_PAGE_CROSS = 4'b1001;
 
 
 
        // OPCODES TODO: verify how this get synthesised
        // OPCODES TODO: verify how this get synthesised
        `include "../T6507LP_Package.v"
        `include "../T6507LP_Package.v"
 
 
        // control signals
        // control signals
        localparam MEM_READ = 1'b0;
        localparam MEM_READ = 1'b0;
        localparam MEM_WRITE = 1'b1;
        localparam MEM_WRITE = 1'b1;
 
 
        reg [12:0] pc;           // program counter
        reg [ADDR_SIZE-1:0] pc;          // program counter
        reg [7:0] sp;            // stack pointer
        reg [DATA_SIZE-1:0] sp;          // stack pointer
        reg [7:0] ir;            // instruction register
        reg [DATA_SIZE-1:0] ir;          // instruction register
        reg [12:0] temp_add;     // temporary address
        reg [ADDR_SIZE:0] temp_add;      // temporary address
        reg [7:0] temp_data;     // temporary data
        reg [DATA_SIZE-1:0] temp_data;   // temporary data
 
 
        reg [3:0] state, next_state; // current and next state registers
        reg [3:0] state, next_state; // current and next state registers
        // TODO: not sure if this will be 4 bits wide. as of march 9th this was 4bit wide.
        // TODO: not sure if this will be 4 bits wide. as of march 9th this was 4bit wide.
 
 
        // wiring that simplifies the FSM logic
        // wiring that simplifies the FSM logic
Line 103... Line 104...
        reg read;
        reg read;
        reg read_modify_write;
        reg read_modify_write;
        reg write;
        reg write;
        reg jump;
        reg jump;
 
 
        reg enable;
        wire [ADDR_SIZE-1:0] next_pc;
 
 
        wire [12:0] next_pc;
 
        assign next_pc = pc + 13'b0000000000001;
        assign next_pc = pc + 13'b0000000000001;
 
 
        always @ (posedge clk_in or negedge n_rst_in) begin
        always @ (posedge clk_in or negedge rst_in_n) begin
                if (n_rst_in == 1'b0) begin
                if (rst_in_n == 1'b0) begin
                        // TODO: all registers must assume default values
                        // TODO: all internal flip-flops must assume default values
 
 
                        pc <= {13{1'b0}}; // TODO: this is written somewhere. something about a reset vector. must be checked.
                        pc <= 0; // TODO: this is written somewhere. something about a reset vector. must be checked.
                        sp <= 8'h00; // TODO: the default is not 0. maybe $0100 or something like that. must be checked.
                        sp <= 0; // TODO: the default is not 0. maybe $0100 or something like that. must be checked.
                        ir <= 8'h00;
                        ir <= 0;
                        temp_add <= {13{1'b0}};
                        temp_add <= 0;
                        temp_data <= {8{1'b0}};
                        temp_data <= 0;
                        state <= FETCH_OP;
                        state <= RESET;
 
 
                        //address <= {13{1'b0}};
 
                        //control <= 1'b0;
 
                        //data_out <= {8{1'b0}};
 
                        //alu_opcode <= {8{1'b0}};
 
                        //alu_a <= {8{1'b0}};
 
                end
                end
                else begin
                else begin
                        state <= next_state;
                        state <= next_state;
 
 
                        address <= pc; // this secures the pipelining will happen by default
 
 
 
                        case (state)
                        case (state)
 
                                RESET: begin
 
                                        // The processor was reset 
 
                                end
                                FETCH_OP: begin // this state is the simplest one. it is a simple fetch that must be done when the cpu was reset or
                                FETCH_OP: begin // this state is the simplest one. it is a simple fetch that must be done when the cpu was reset or
                                                // the last cycle was a memory write.
                                                // the last cycle was a memory write.
                                        pc <= next_pc;
                                        pc <= next_pc;
                                end
                                end
                                FETCH_LOW: begin // in this state the opcode is already known so truly execution begins
                                FETCH_OP_CALC: begin // this is the pipeline happening!
                                        pc <= next_pc;
 
                                        ir <= data_in; // opcode must be saved in the instruction register. this is not necessary for the IMP and ACC modes.
 
                                end
 
                                FETCH_HIGH: begin
 
                                        pc <= next_pc;
                                        pc <= next_pc;
 
 
                                        temp_add <= {5'b00000, data_in}; // data from previous cycle (lowbyte) is ready and must be saved
 
                                end
 
                                SET_PC: begin
 
                                        pc <= {data_in[4:0], temp_add[7:0]};
 
                                end
 
                                READ_EFFECTIVE: begin
 
                                        if (zero_page) begin
 
                                                temp_add <= {5'b00000, data_in}; // this is necessary for the write_effective state
 
                                                address <= {5'b00000, data_in};
 
                                        end
 
                                        else if (zero_page_indexed) begin
 
                                                temp_add <= {5'b00000, alu_result}; // this is necessary for the write_effective state
 
                                                address <= {5'b00000, alu_result};
 
                                        end
 
                                        else begin
 
                                                temp_add[12:8] <= data_in;
 
                                                address <= {data_in[4:0], temp_add[7:0]};
 
                                        end
 
                                end
 
                                DO_OPERATION, CALCULATE_INDEX: begin
 
                                end
 
                                WRITE_DUMMY: begin
 
                                        //if (zero_page) begin // i believe this works fine
 
 
 
                                        address <= temp_add;
 
                                        //control <= WRITE; // just for compatibility
 
                                        //alu_opcode <= ir;
 
                                        //alu_a <= data_in;
 
                                end
                                end
                                WRITE_EFFECTIVE: begin
                                FETCH_LOW: begin // in this state the opcode is already known so truly execution begins
                                        if (zero_page) begin
                                        if (accumulator || implied) begin
                                                address <= temp_add;
                                                pc <= pc; // is this necessary?
                                        end
 
                                        else if (zero_page_indexed) begin
 
                                                address <= {5'b00000, alu_result};
 
                                        end
 
                                        else begin // maybe this could be rearenged for better synth
 
                                                if (write) begin
 
                                                        address <= {data_in[4:0], temp_add[7:0]};
 
                                                end
                                                end
                                                else begin
                                                else begin
                                                        address <= temp_add;
                                                pc <= next_pc;
                                                end
                                                ir <= data_in; // opcode must be saved in the instruction register
                                        end
 
 
 
                                        //data_out <= alu_result;
 
                                        //control <= WRITE;
 
                                end
                                end
                                CHECK_FOR_PAGE_CROSS: begin
 
                                        temp_add[12:8] <= data_in;
 
                                        address <= {data_in[4:0], temp_add[7:0]};
 
                                end
                                end
                                default: begin
                                default: begin
                                        state <= FETCH_OP;              // TODO: this prevents the system from halting but may trigger strange behavior.
                                        $write("unknown state");        // TODO: check if synth really ignores this 2 lines. Otherwise wrap it with a `ifdef 
                                        $finish("UNKNOWN STATE!");      // TODO: check if synth really ignores this line. Otherwise wrap it with a `ifdef 
                                        $finish(0);
                                end
                                end
 
 
                        endcase
                        endcase
                end
                end
        end
        end
 
 
        always @(posedge clk_in) begin // combinational block that handles the outputs
        always @ (*) begin // this is the next_state logic and output logic always block
                enable <= 1'b0;
                address = pc;
                control <= MEM_READ;
                control = MEM_READ;
                alu_opcode <= 8'h00;
                data_out = 8'h00;
                alu_a <= 8'h00;
                alu_opcode = 8'h00;
                data_out <= 8'h00;
                alu_a = 8'h00;
 
                alu_enable = 1'b0;
                case (state)
 
                        FETCH_OP, SET_PC, READ_EFFECTIVE: begin
 
                                //enable = 0;
 
                        end
 
                        FETCH_LOW: begin
 
                                if (accumulator || implied) begin // the ALU must be used
 
                                        enable <= 1'b1;
 
                                        alu_opcode <= data_in;
 
                                end
 
                        end
 
                        FETCH_HIGH: begin
 
                                if (immediate || write || absolute_indexed) begin
 
                                        enable <= 1'b1;
 
                                        alu_opcode <= ir;
 
                                        alu_a <= data_in;
 
                                end
 
                        end
 
                        DO_OPERATION, CALCULATE_INDEX: begin
 
                                enable <= 1'b1;
 
                                alu_opcode <= ir;
 
                                alu_a <= data_in;
 
                        end
 
                        WRITE_DUMMY: begin
 
                                //if (zero_page) begin // i believe this works fine
 
                                control <= MEM_WRITE;   // just for compatibility
 
                                data_out <= data_in;    // just for compatibility
 
                                alu_opcode <= ir;
 
                                alu_a <= data_in;
 
                        end
 
                        WRITE_EFFECTIVE: begin
 
                                control <= MEM_WRITE;
 
                                data_out <= alu_result;
 
                        end
 
                endcase
 
        end
 
 
 
        always @ (*) begin // this is the next_state always
 
 
 
                next_state = FETCH_OP; // this should avoid latch inferring
                next_state = RESET; // this prevents the latch 
 
 
                begin
                begin
                        case (state)
                        case (state)
                                FETCH_OP: begin
                                RESET: begin
                                        next_state = FETCH_LOW;
                                        next_state = FETCH_OP;
                                end
 
                                FETCH_LOW: begin
 
                                        if (accumulator  || implied) begin
 
                                                next_state = FETCH_OP; // not sure
 
                                        end
 
                                        else if (zero_page) begin // zero page behaves exactly as absolute except that it has only the first fetch
 
                                                if (read || read_modify_write) begin
 
                                                        next_state = READ_EFFECTIVE;
 
                                                end
 
                                                else if (write) begin
 
                                                        next_state = WRITE_EFFECTIVE;
 
                                                end
 
                                        end
 
                                        else if (zero_page_indexed) begin
 
                                                next_state = CALCULATE_INDEX;
 
                                        end
 
                                        else begin
 
                                                next_state = FETCH_HIGH;
 
                                        end
 
                                end
                                end
                                FETCH_HIGH: begin
                                FETCH_OP: begin
                                        if (immediate) begin
 
                                                next_state = FETCH_LOW;
                                                next_state = FETCH_LOW;
                                        end
                                        end
                                        else if (absolute) begin
                                FETCH_OP_CALC: begin
                                                if (jump) begin
 
                                                        next_state = SET_PC;
 
                                                end
 
                                                else if (read || read_modify_write) begin // TODO: verify if this should stay like this 
 
                                                        // (LDA, LDX, LDY, EOR, AND, ORA, ADC, SBC, CMP, BIT, LAX, NOP) reads
 
                                                        // (ASL, LSR, ROL, ROR, INC, DEC, SLO, SRE, RLA, RRA, ISB, DCP) modifs
 
                                                        // (STA, STX, STY, SAX) writes
 
                                                        next_state = READ_EFFECTIVE;
 
                                                end
 
                                                else if (write) begin
 
                                                        next_state = WRITE_EFFECTIVE;
 
                                                end
 
                                        end
 
                                        else if (absolute_indexed) begin
 
                                                next_state = CHECK_FOR_PAGE_CROSS;
 
                                        end
 
                                end
 
                                SET_PC, DO_OPERATION: begin
 
                                        next_state = FETCH_LOW;
                                        next_state = FETCH_LOW;
 
                                        alu_opcode = ir;
 
                                        alu_enable = 1'b1;
                                end
                                end
                                READ_EFFECTIVE: begin
                                FETCH_LOW: begin
                                        if (read) begin
                                        if (accumulator  || implied) begin
                                                next_state = DO_OPERATION;
                                                alu_opcode = data_in;
                                        end
                                                alu_enable = 1'b1;
                                        else if (read_modify_write) begin
 
                                                next_state = WRITE_DUMMY;
 
                                        end
 
                                end
 
                                WRITE_EFFECTIVE: begin
 
                                        next_state = FETCH_OP;
                                        next_state = FETCH_OP;
                                end
                                end
                                CALCULATE_INDEX: begin
                                        else if (immediate) begin
                                        if (read || read_modify_write) begin
                                                next_state = FETCH_OP_CALC;
                                                next_state = READ_EFFECTIVE;
 
                                        end
 
                                        else if (write) begin
 
                                                next_state = WRITE_EFFECTIVE;
 
                                        end
 
                                end
 
                                CHECK_FOR_PAGE_CROSS: begin
 
                                        if (alu_status[V] == 1'b0) begin // check the overflow bit
 
                                                if (read || read_modify_write) begin
 
                                                        next_state = READ_EFFECTIVE;
 
                                                end
 
                                                else begin
 
                                                        next_state = WRITE_EFFECTIVE;
 
                                                end
 
                                        end
 
                                        else begin // TODO: this is totally uncertain. absolute indexed mode must be reviewed
 
                                                if (read || read_modify_write) begin
 
                                                        next_state = DO_OPERATION;
 
                                                end
                                                end
                                                else begin
                                        else begin // at least the immediate address mode falls here
                                                        next_state = WRITE_EFFECTIVE;
                                                next_state = FETCH_HIGH;
                                                end
                                                end
                                        end
                                        end
 
                                default: begin
 
                                        next_state = RESET;
                                        end
                                        end
                                //end
 
 
 
                        endcase
                        endcase
                end
                end
        end
        end
 
 
        // this always block is responsible for updating the address mode
        // this always block is responsible for updating the address mode
        always @ (*) begin // TODO: the sensitivity may not be correct 
        always @ (*) begin // 
 
 
                absolute = 1'b0;
                absolute = 1'b0;
                absolute_indexed = 1'b0;
                absolute_indexed = 1'b0;
                accumulator = 1'b0;
                accumulator = 1'b0;
                immediate = 1'b0;
                immediate = 1'b0;
                implied = 1'b0;
                implied = 1'b0;
Line 361... Line 210...
                read = 1'b0;
                read = 1'b0;
                read_modify_write = 1'b0;
                read_modify_write = 1'b0;
                write = 1'b0;
                write = 1'b0;
                jump = 1'b0;
                jump = 1'b0;
 
 
                if (state == FETCH_LOW) begin // TODO: does this works?
                if (state == FETCH_LOW) begin
                        case (data_in)
                        case (data_in)
                                BRK_IMP, CLC_IMP, CLD_IMP, CLI_IMP, CLV_IMP, DEX_IMP, DEY_IMP, INX_IMP, INY_IMP, NOP_IMP, PHA_IMP, PHP_IMP, PLA_IMP,
                                BRK_IMP, CLC_IMP, CLD_IMP, CLI_IMP, CLV_IMP, DEX_IMP, DEY_IMP, INX_IMP, INY_IMP, NOP_IMP, PHA_IMP, PHP_IMP, PLA_IMP,
                                PLP_IMP, RTI_IMP, RTS_IMP, SEC_IMP, SED_IMP, SEI_IMP, TAX_IMP, TAY_IMP, TSX_IMP, TXA_IMP, TXS_IMP, TYA_IMP: begin
                                PLP_IMP, RTI_IMP, RTS_IMP, SEC_IMP, SED_IMP, SEI_IMP, TAX_IMP, TAY_IMP, TSX_IMP, TXA_IMP, TXS_IMP, TYA_IMP: begin
                                        implied = 1'b1;
                                        implied = 1'b1;
                                end
                                end

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.