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

Subversion Repositories t6507lp

[/] [t6507lp/] [trunk/] [rtl/] [verilog/] [t6507lp_fsm.v] - Diff between revs 70 and 71

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

Rev 70 Rev 71
Line 46... Line 46...
////                                                                    ////
////                                                                    ////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
 
 
`timescale 1ns / 1ps
`timescale 1ns / 1ps
 
 
module t6507lp_fsm(clk_in, rst_in_n, alu_result, alu_status, data_in, address, control, data_out, alu_opcode, alu_a, alu_enable);
module t6507lp_fsm(clk, reset_n, alu_result, alu_status, data_in, address, control, data_out, alu_opcode, alu_a, alu_enable);
 
 
        parameter DATA_SIZE = 4'd8;
        parameter DATA_SIZE = 4'd8;
        parameter ADDR_SIZE = 4'd13;
        parameter ADDR_SIZE = 4'd13;
 
 
        input clk_in;
        input clk;
        input rst_in_n;
        input reset_n;
        input [DATA_SIZE-1:0] alu_result;
        input [DATA_SIZE-1:0] alu_result;
        input [DATA_SIZE-1:0] alu_status;
        input [DATA_SIZE-1:0] alu_status;
        input [DATA_SIZE-1:0] data_in;
        input [DATA_SIZE-1:0] data_in;
        output reg [ADDR_SIZE-1: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
Line 70... Line 69...
        localparam RESET = 4'b1111;
        localparam RESET = 4'b1111;
        localparam FETCH_OP = 4'b0000;
        localparam FETCH_OP = 4'b0000;
        localparam FETCH_OP_CALC = 4'b0001;
        localparam FETCH_OP_CALC = 4'b0001;
        localparam FETCH_LOW = 4'b0010;
        localparam FETCH_LOW = 4'b0010;
        localparam FETCH_HIGH = 4'b0011;
        localparam FETCH_HIGH = 4'b0011;
 
        localparam READ_MEM = 4'b0100;
 
        localparam DUMMY_WRT_CALC = 4'b0101;
 
        localparam WRITE_MEM = 4'b0110;
 
        localparam FETCH_OP_CALC_PARAM = 4'b0111;
 
 
        // 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
Line 81... Line 84...
        localparam MEM_WRITE = 1'b1;
        localparam MEM_WRITE = 1'b1;
 
 
        reg [ADDR_SIZE-1:0] pc;          // program counter
        reg [ADDR_SIZE-1:0] pc;          // program counter
        reg [DATA_SIZE-1:0] sp;          // stack pointer
        reg [DATA_SIZE-1:0] sp;          // stack pointer
        reg [DATA_SIZE-1:0] ir;          // instruction register
        reg [DATA_SIZE-1:0] ir;          // instruction register
        reg [ADDR_SIZE:0] temp_add;      // temporary address
        reg [ADDR_SIZE:0] temp_addr;     // temporary address
        reg [DATA_SIZE-1: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.
 
 
Line 107... Line 110...
        reg jump;
        reg jump;
 
 
        wire [ADDR_SIZE-1:0] next_pc;
        wire [ADDR_SIZE-1:0] next_pc;
        assign next_pc = pc + 13'b0000000000001;
        assign next_pc = pc + 13'b0000000000001;
 
 
        always @ (posedge clk_in or negedge rst_in_n) begin // sequencial always block
        always @ (posedge clk or negedge reset_n) begin // sequencial always block
                if (rst_in_n == 1'b0) begin
                if (reset_n == 1'b0) begin
                        // TODO: all internal flip-flops must assume default values
                        // all registers must assume default values
 
 
                        pc <= 0; // 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 <= 0; // 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 <= 0;
                        ir <= 0;
                        temp_add <= 0;
                        temp_addr <= 0;
                        temp_data <= 0;
                        temp_data <= 0;
                        state <= RESET;
                        state <= RESET;
 
                        // registered outputs also receive default values
 
                        address <= 0;
 
                        control <= 0; // check if these 2 shouldnt be on the other always block along with the address
 
                        data_out <= 0;
                end
                end
                else begin
                else begin
                        state <= next_state;
                        state <= next_state;
 
                        control <= MEM_READ;
 
 
                        case (state)
                        case (state)
                                RESET: begin
                                RESET: begin
                                        // The processor was reset 
                                        // The processor was reset 
                                end
                                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;
 
                                        address <= next_pc;
                                        ir <= data_in;
                                        ir <= data_in;
                                end
                                end
                                FETCH_OP_CALC: begin // this is the pipeline happening!
                                FETCH_OP_CALC, FETCH_OP_CALC_PARAM: begin // this is the pipeline happening!
                                        pc <= next_pc;
                                        pc <= next_pc;
 
                                        address <= next_pc;
                                        ir <= data_in;
                                        ir <= data_in;
                                end
                                end
                                FETCH_LOW: begin // in this state the opcode is already known so truly execution begins
                                FETCH_LOW: begin // in this state the opcode is already known so truly execution begins
                                        if (accumulator || implied) begin
                                        if (accumulator || implied) begin
                                                pc <= pc; // is this better?
                                                pc <= pc; // is this better?
 
                                                address <= pc;
                                        end
                                        end
                                        else if (immediate) begin
                                        else if (immediate) begin
                                                pc <= next_pc;
                                                pc <= next_pc;
 
                                                address <= next_pc;
                                                temp_data <= data_in; // the follow-up byte is saved in temp_data 
                                                temp_data <= data_in; // the follow-up byte is saved in temp_data 
                                        end
                                        end
 
                                        else if (absolute) begin
 
                                                pc <= next_pc;
 
                                                address <= next_pc;
 
                                                temp_addr[7:0] <= data_in;
                                end
                                end
                                default: begin
 
                                        $write("unknown state");        // TODO: check if synth really ignores this 2 lines. Otherwise wrap it with a `ifdef 
 
                                        $finish(0);
 
                                end
                                end
 
                                FETCH_HIGH: begin
                        endcase
                                        if (jump) begin
 
                                                pc <= {data_in[4:0], temp_addr}; // PCL <= first byte, PCH <= second byte
 
                                                address <= {data_in[4:0], temp_addr};
                end
                end
 
                                        else begin
 
                                                if (write) begin
 
                                                        pc <= next_pc;
 
                                                        temp_addr[12:8] <= data_in[4:0];
 
                                                        address <= {data_in[4:0],temp_addr[7:0]};
 
                                                        control <= MEM_WRITE;
        end
        end
 
                                                else begin // read_modify_write or just read
        always @ (posedge clk_in or negedge rst_in_n) begin
                                                        pc <= next_pc;
                if (rst_in_n == 1'b0) begin
                                                        temp_addr[12:8] <= data_in[4:0];
                        // TODO: all outputs must assume default values
                                                        address <= {data_in[4:0],temp_addr[7:0]};
                        address <= 0;
 
                        control <= 0; // one bit is enough? read = 0, write = 1
 
                        data_out <= 0;
 
                        alu_opcode <= 0;
 
                        alu_a <= 0;
 
                        alu_enable <= 0;
 
                end
                end
                else begin
 
 
 
                        address <= pc;
 
 
 
                        case (state)
 
                                RESET: begin
 
                                        // The processor was reset. No output whatsoever. 
 
                                end
                                end
                                FETCH_OP: begin
                                        //else begin
                                        // it is a simple fetch. no output change.
                                        //      $write("FETCHHIGH PROBLEM"); 
 
                                        //      $finish(0); 
 
                                        //end
 
                                end
 
                                READ_MEM: begin
 
                                        if (read_modify_write) begin
 
                                                pc <= pc;
 
                                                address <= temp_addr;
 
                                                control <= MEM_WRITE;
 
                                                temp_data <= data_in;
 
                                                data_out <= data_in; // writeback the same value
                                end
                                end
                                FETCH_OP_CALC: begin // this is the pipeline happening!
                                        else begin
                                        alu_opcode <= ir;
                                                pc <= pc;
                                        alu_a <= temp_data;
                                                address <= pc;
                                        alu_enable <= 1'b1;
                                                temp_data <= data_in;
                                end
                                end
                                FETCH_LOW: begin // in this state the opcode is already known so truly execution begins
 
                                        if (accumulator || implied) begin
 
                                                alu_opcode <= ir;
 
                                                alu_enable <= 1'b1;
 
                                        end
                                        end
                                        else begin // nothing?
                                DUMMY_WRT_CALC: begin
 
                                        pc <= pc;
 
                                        address <= temp_addr;
 
                                        control <= MEM_WRITE;
 
                                        data_out <= alu_result;
                                        end
                                        end
 
                                WRITE_MEM: begin
 
                                        pc <= pc;
 
                                        address <= pc;
 
                                        data_out = 8'hzz;
                                end
                                end
                                default: begin
                                default: begin
                                        $write("unknown state");        // TODO: check if synth really ignores this 2 lines. Otherwise wrap it with a `ifdef 
                                        $write("unknown state");        // TODO: check if synth really ignores this 2 lines. Otherwise wrap it with a `ifdef 
                                        $finish(0);
                                        $finish(0);
                                end
                                end
 
 
                        endcase
                        endcase
                end
                end
 
 
        end
        end
 
 
        always @ (*) begin // this is the next_state logic always block
        always @ (*) begin // this is the next_state logic and the output logic always block
                //address = pc;
 
                //control = MEM_READ; 
                //control = MEM_READ; 
                //data_out = 8'h00;
                //data_out = 8'h00;
                //alu_opcode = 8'h00;
 
                //alu_a = 8'h00;
                alu_opcode = 8'h00;
                //alu_enable = 1'b0;
                alu_a = 8'h00;
 
                alu_enable = 1'b0;
 
                //address = pc;
 
 
                next_state = RESET; // this prevents the latch 
                next_state = RESET; // this prevents the latch 
 
 
                begin
 
                        case (state)
                        case (state)
                                RESET: begin
                                RESET: begin
                                        next_state = FETCH_OP;
                                        next_state = FETCH_OP;
                                end
                                end
                                FETCH_OP: begin
                                FETCH_OP: begin
                                        next_state = FETCH_LOW;
                                        next_state = FETCH_LOW;
 
                                //address = pc;
                                end
                                end
                                FETCH_OP_CALC: begin
                                FETCH_OP_CALC: begin
                                        next_state = FETCH_LOW;
                                        next_state = FETCH_LOW;
                                        //alu_opcode = ir;
                                alu_opcode = ir;
                                        //alu_enable = 1'b1;
                                alu_enable = 1'b1;
 
                                //address = next_pc;
 
 
 
                        end
 
                        FETCH_OP_CALC_PARAM: begin
 
                                next_state = FETCH_LOW;
 
                                alu_opcode = ir;
 
                                alu_enable = 1'b1;
 
                                alu_a = temp_data;
 
                                //address = next_pc;
                                end
                                end
                                FETCH_LOW: begin
                                FETCH_LOW: begin
                                        if (accumulator  || implied) begin
                                        if (accumulator  || implied) begin
                                                //alu_opcode = data_in;
                                        alu_opcode = ir;
                                                //alu_enable = 1'b1;
                                        alu_enable = 1'b1;
                                                next_state = FETCH_OP;
                                                next_state = FETCH_OP;
                                        end
                                        end
                                        else if (immediate) begin
                                        else if (immediate) begin
                                                next_state = FETCH_OP_CALC;
                                        next_state = FETCH_OP_CALC_PARAM;
                                        end
                                        end
                                        else begin // at least the immediate address mode falls here
                                else begin // at least the absolute address mode falls here
                                                next_state = FETCH_HIGH;
                                                next_state = FETCH_HIGH;
                                        end
                                        end
 
                                //address = next_pc;
 
 
 
                        end
 
                        FETCH_HIGH: begin
 
                                if (jump) begin
 
                                        next_state = FETCH_OP;
 
                                end
 
                                else if (read || read_modify_write) begin
 
                                        next_state = READ_MEM;
 
                                end
 
                                else if (write) begin
 
                                        next_state = WRITE_MEM;
 
                                end
 
                                else begin
 
                                        $write("unknown behavior");
 
                                        $finish(0);
 
                                end
 
                        end
 
                        READ_MEM: begin
 
                                if (read) begin
 
                                        next_state = FETCH_OP_CALC_PARAM;
 
                                end
 
                                else if (read_modify_write) begin
 
                                        next_state = DUMMY_WRT_CALC;
 
                                end
 
                        end
 
                        DUMMY_WRT_CALC: begin
 
                                alu_opcode = ir;
 
                                alu_enable = 1'b1;
 
                                alu_a = data_in;
 
                                next_state = WRITE_MEM;
 
                        end
 
                        WRITE_MEM: begin
 
                                next_state = FETCH_OP;
                                end
                                end
                                default: begin
                                default: begin
                                        next_state = RESET;
                                        next_state = RESET;
                                end
                                end
                        endcase
                        endcase
                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 // 
        always @ (*) begin // 
                absolute = 1'b0;
                absolute = 1'b0;
                absolute_indexed = 1'b0;
                absolute_indexed = 1'b0;
Line 291... Line 353...
                        end
                        end
                        ADC_IDX, AND_IDX, CMP_IDX, EOR_IDX, LDA_IDX, ORA_IDX, SBC_IDX, STA_IDX, ADC_IDY, AND_IDY, CMP_IDY, EOR_IDY, LDA_IDY,
                        ADC_IDX, AND_IDX, CMP_IDX, EOR_IDX, LDA_IDX, ORA_IDX, SBC_IDX, STA_IDX, ADC_IDY, AND_IDY, CMP_IDY, EOR_IDY, LDA_IDY,
                        ORA_IDY, SBC_IDY, STA_IDY: begin // all these opcodes are 8'hX1; TODO: optimize this
                        ORA_IDY, SBC_IDY, STA_IDY: begin // all these opcodes are 8'hX1; TODO: optimize this
                                indirect = 1'b1;
                                indirect = 1'b1;
                        end
                        end
 
                        default: begin
 
                                $write("unknown OPCODE!");
 
                                $finish();
 
                        end
                endcase
                endcase
 
 
                if (data_in == JMP_ABS || data_in == JMP_IND) begin // the opcodes are 8'h4C and 8'h6C
                case (ir)
                        jump = 1'b1;
                        ASL_ACC, ASL_ZPG, ASL_ZPX, ASL_ABS, ASL_ABX, LSR_ACC, LSR_ZPG, LSR_ZPX, LSR_ABS, LSR_ABX, ROL_ACC, ROL_ZPG, ROL_ZPX, ROL_ABS,
 
                        ROL_ABX, ROR_ACC, ROR_ZPG, ROR_ZPX, ROR_ABS, ROR_ABX, INC_ZPG, INC_ZPX, INC_ABS, INC_ABX, DEC_ZPG, DEC_ZPX, DEC_ABS,
 
                        DEC_ABX: begin
 
                                read_modify_write = 1'b1;
                end
                end
 
                        STA_ZPG, STA_ZPX, STA_ABS, STA_ABX, STA_ABY, STA_IDX, STA_IDY, STX_ZPG, STX_ZPY, STX_ABS, STY_ZPG, STY_ZPX, STY_ABS: begin
 
                                write = 1'b1;
 
                        end
 
                        default: begin // this should work fine since the previous case statement will detect the unknown/undocumented/unsupported opcodes
 
                                read = 1'b1;
 
                        end
 
                endcase
 
 
                //      if (data_in == )
                if (ir == JMP_ABS || ir == JMP_IND) begin // the opcodes are 8'h4C and 8'h6C
 
                        jump = 1'b1;
/*LDA_IMM = 8'hA9,
                end
LDA_ZPG = 8'hA5,
 
LDA_ZPX = 8'hB5,
 
LDA_ABS = 8'hAD,
 
LDA_ABX = 8'hBD,
 
LDA_ABY = 8'hB9,
 
LDA_IDX = 8'hA1,
 
LDA_IDY = 8'hB1;
 
LDX_IMM = 8'hA2,
 
LDX_ZPG = 8'hA6,
 
LDX_ZPY = 8'hB6,
 
LDX_ABS = 8'hAE,
 
LDX_ABY = 8'hBE;
 
LDY_IMM = 8'hA0,
 
LDY_ZPG = 8'hA4,
 
LDY_ZPX = 8'hB4,
 
LDY_ABS = 8'hAC,
 
LDY_ABX = 8'hBC;
 
*/
 
 
 
        end // no way
        end // no way
endmodule
endmodule
 
 
 
 
 
 

powered by: WebSVN 2.1.0

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