////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// T6507LP IP Core ////
|
//// T6507LP IP Core ////
|
//// ////
|
//// ////
|
//// This file is part of the T6507LP project ////
|
//// This file is part of the T6507LP project ////
|
//// http://www.opencores.org/cores/t6507lp/ ////
|
//// http://www.opencores.org/cores/t6507lp/ ////
|
//// ////
|
//// ////
|
//// Description ////
|
//// Description ////
|
//// 6507 FSM ////
|
//// 6507 FSM ////
|
//// ////
|
//// ////
|
//// TODO: ////
|
//// TODO: ////
|
//// - Fix relative mode, bit 7 means negative ////
|
//// - Fix relative mode, bit 7 means negative ////
|
//// - Check reset behavior ////
|
//// - Check reset behavior ////
|
//// - Comment the code ////
|
//// - Comment the code ////
|
//// ////
|
//// ////
|
//// Author(s): ////
|
//// Author(s): ////
|
//// - Gabriel Oshiro Zardo, gabrieloshiro@gmail.com ////
|
//// - Gabriel Oshiro Zardo, gabrieloshiro@gmail.com ////
|
//// - Samuel Nascimento Pagliarini (creep), snpagliarini@gmail.com ////
|
//// - Samuel Nascimento Pagliarini (creep), snpagliarini@gmail.com ////
|
//// ////
|
//// ////
|
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2001 Authors and OPENCORES.ORG ////
|
//// Copyright (C) 2001 Authors and OPENCORES.ORG ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
|
|
`include "timescale.v"
|
`include "timescale.v"
|
|
|
module t6507lp_fsm(clk, reset_n, alu_result, alu_status, data_in, alu_x, alu_y, address, mem_rw, data_out, alu_opcode, alu_a, alu_enable);
|
module t6507lp_fsm(clk, reset_n, alu_result, alu_status, data_in, alu_x, alu_y, address, mem_rw, data_out, alu_opcode, alu_a, alu_enable);
|
parameter [3:0] DATA_SIZE = 4'd8;
|
parameter [3:0] DATA_SIZE = 4'd8;
|
parameter [3:0] ADDR_SIZE = 4'd13;
|
parameter [3:0] ADDR_SIZE = 4'd13;
|
|
|
localparam [3:0] DATA_SIZE_ = DATA_SIZE - 4'b0001;
|
localparam [3:0] DATA_SIZE_ = DATA_SIZE - 4'b0001;
|
localparam [3:0] ADDR_SIZE_ = ADDR_SIZE - 4'b0001;
|
localparam [3:0] ADDR_SIZE_ = ADDR_SIZE - 4'b0001;
|
|
|
input clk; // master clock
|
input clk; // master clock
|
input reset_n; // active low reset
|
input reset_n; // active low reset
|
input [DATA_SIZE_:0] alu_result; // result from alu operation
|
input [DATA_SIZE_:0] alu_result; // result from alu operation
|
input [DATA_SIZE_:0] alu_status; // alu status register
|
input [DATA_SIZE_:0] alu_status; // alu status register
|
input [DATA_SIZE_:0] data_in; // data that comes from the bus controller
|
input [DATA_SIZE_:0] data_in; // data that comes from the bus controller
|
input [DATA_SIZE_:0] alu_x; // alu x index register
|
input [DATA_SIZE_:0] alu_x; // alu x index register
|
input [DATA_SIZE_:0] alu_y; // alu y index register
|
input [DATA_SIZE_:0] alu_y; // alu y index register
|
output reg [ADDR_SIZE_:0] address; // system bus address
|
output reg [ADDR_SIZE_:0] address; // system bus address
|
output reg mem_rw; // read = 0, write = 1
|
output reg mem_rw; // read = 0, write = 1
|
output reg [DATA_SIZE_:0] data_out; // data that will be written somewhere else
|
output reg [DATA_SIZE_:0] data_out; // data that will be written somewhere else
|
output reg [DATA_SIZE_:0] alu_opcode; // current opcode
|
output reg [DATA_SIZE_:0] alu_opcode; // current opcode
|
output reg [DATA_SIZE_:0] alu_a; // extra operand sent to the alu
|
output reg [DATA_SIZE_:0] alu_a; // extra operand sent to the alu
|
output reg alu_enable; // a flag that when high tells the alu when to perform the operations
|
output reg alu_enable; // a flag that when high tells the alu when to perform the operations
|
|
|
|
|
// FSM states. If aiming for less power consumption try gray coding.
|
// FSM states. If aiming for less power consumption try gray coding.
|
//localparam FETCH_OP_CALC = 5'b00001; this was never used
|
//localparam FETCH_OP_CALC = 5'b00001; this was never used
|
localparam FETCH_OP = 5'b00000;
|
localparam FETCH_OP = 5'b00000;
|
localparam FETCH_LOW = 5'b00010;
|
localparam FETCH_LOW = 5'b00010;
|
localparam FETCH_HIGH = 5'b00011;
|
localparam FETCH_HIGH = 5'b00011;
|
localparam READ_MEM = 5'b00100;
|
localparam READ_MEM = 5'b00100;
|
localparam DUMMY_WRT_CALC = 5'b00101;
|
localparam DUMMY_WRT_CALC = 5'b00101;
|
localparam WRITE_MEM = 5'b00110;
|
localparam WRITE_MEM = 5'b00110;
|
localparam FETCH_OP_CALC_PARAM = 5'b00111;
|
localparam FETCH_OP_CALC_PARAM = 5'b00111;
|
localparam READ_MEM_CALC_INDEX = 5'b01000;
|
localparam READ_MEM_CALC_INDEX = 5'b01000;
|
localparam FETCH_HIGH_CALC_INDEX = 5'b01001;
|
localparam FETCH_HIGH_CALC_INDEX = 5'b01001;
|
localparam READ_MEM_FIX_ADDR = 5'b01010;
|
localparam READ_MEM_FIX_ADDR = 5'b01010;
|
localparam FETCH_OP_EVAL_BRANCH = 5'b01011;
|
localparam FETCH_OP_EVAL_BRANCH = 5'b01011;
|
localparam FETCH_OP_FIX_PC = 5'b01100;
|
localparam FETCH_OP_FIX_PC = 5'b01100;
|
localparam READ_FROM_POINTER = 5'b01101;
|
localparam READ_FROM_POINTER = 5'b01101;
|
localparam READ_FROM_POINTER_X = 5'b01110;
|
localparam READ_FROM_POINTER_X = 5'b01110;
|
localparam READ_FROM_POINTER_X1 = 5'b01111;
|
localparam READ_FROM_POINTER_X1 = 5'b01111;
|
localparam PUSH_PCH = 5'b10000;
|
localparam PUSH_PCH = 5'b10000;
|
localparam PUSH_PCL = 5'b10001;
|
localparam PUSH_PCL = 5'b10001;
|
localparam PUSH_STATUS = 5'b10010;
|
localparam PUSH_STATUS = 5'b10010;
|
localparam FETCH_PCL = 5'b10011;
|
localparam FETCH_PCL = 5'b10011;
|
localparam FETCH_PCH = 5'b10100;
|
localparam FETCH_PCH = 5'b10100;
|
localparam INCREMENT_SP = 5'b10101;
|
localparam INCREMENT_SP = 5'b10101;
|
localparam PULL_STATUS = 5'b10110;
|
localparam PULL_STATUS = 5'b10110;
|
localparam PULL_PCL = 5'b10111;
|
localparam PULL_PCL = 5'b10111;
|
localparam PULL_PCH = 5'b11000;
|
localparam PULL_PCH = 5'b11000;
|
localparam INCREMENT_PC = 5'b11001;
|
localparam INCREMENT_PC = 5'b11001;
|
localparam PUSH_REGISTER = 5'b11010;
|
localparam PUSH_REGISTER = 5'b11010;
|
localparam PULL_REGISTER = 5'b11011;
|
localparam PULL_REGISTER = 5'b11011;
|
localparam DUMMY = 5'b11100;
|
localparam DUMMY = 5'b11100;
|
localparam RESET = 5'b11111;
|
localparam RESET = 5'b11111;
|
|
|
// OPCODES TODO: verify how this get synthesised
|
// OPCODES TODO: verify how this get synthesised
|
`include "t6507lp_package.v"
|
`include "t6507lp_package.v"
|
|
|
// mem_rw signals
|
// mem_rw signals
|
localparam MEM_READ = 1'b0;
|
localparam MEM_READ = 1'b0;
|
localparam MEM_WRITE = 1'b1;
|
localparam MEM_WRITE = 1'b1;
|
|
|
reg [ADDR_SIZE_:0] pc; // program counter
|
reg [ADDR_SIZE_:0] pc; // program counter
|
reg [DATA_SIZE:0] sp; // stack pointer. 9 bits wide.
|
reg [DATA_SIZE:0] sp; // stack pointer. 9 bits wide.
|
reg [DATA_SIZE_:0] ir; // instruction register
|
reg [DATA_SIZE_:0] ir; // instruction register
|
reg [ADDR_SIZE_:0] temp_addr; // temporary address
|
reg [ADDR_SIZE_:0] temp_addr; // temporary address
|
reg [DATA_SIZE_:0] temp_data; // temporary data
|
reg [DATA_SIZE_:0] temp_data; // temporary data
|
|
|
reg [4:0] state, next_state; // current and next state registers
|
reg [4:0] state, next_state; // current and next state registers
|
|
|
// wiring that simplifies the FSM logic by simplifying the addressing modes
|
// wiring that simplifies the FSM logic by simplifying the addressing modes
|
reg absolute;
|
reg absolute;
|
reg absolute_indexed;
|
reg absolute_indexed;
|
reg accumulator;
|
reg accumulator;
|
reg immediate;
|
reg immediate;
|
reg implied;
|
reg implied;
|
reg indirectx;
|
reg indirectx;
|
reg indirecty;
|
reg indirecty;
|
reg relative;
|
reg relative;
|
reg zero_page;
|
reg zero_page;
|
reg zero_page_indexed;
|
reg zero_page_indexed;
|
reg [DATA_SIZE_:0] index; // will be assigned with either X or Y
|
reg [DATA_SIZE_:0] index; // will be assigned with either X or Y
|
|
|
// regs that store the type of operation. again, this simplifies the FSM a lot.
|
// regs that store the type of operation. again, this simplifies the FSM a lot.
|
reg read;
|
reg read;
|
reg read_modify_write;
|
reg read_modify_write;
|
reg write;
|
reg write;
|
reg jump;
|
reg jump;
|
reg jump_indirect;
|
reg jump_indirect;
|
reg index_is_x;
|
reg index_is_x;
|
reg index_is_branch;
|
reg index_is_branch;
|
|
|
// regs for the special instructions
|
// regs for the special instructions
|
reg brk;
|
reg brk;
|
reg rti;
|
reg rti;
|
reg rts;
|
reg rts;
|
reg pha;
|
reg pha;
|
reg php;
|
reg php;
|
reg pla;
|
reg pla;
|
reg plp;
|
reg plp;
|
reg jsr;
|
reg jsr;
|
reg tsx;
|
reg tsx;
|
reg txs;
|
reg txs;
|
reg nop;
|
reg nop;
|
|
|
wire [ADDR_SIZE_:0] next_pc; // a simple logic to add one to the PC
|
wire [ADDR_SIZE_:0] next_pc; // a simple logic to add one to the PC
|
assign next_pc = pc + 13'b0000000000001;
|
assign next_pc = pc + 13'b0000000000001;
|
|
|
wire [DATA_SIZE:0] sp_plus_one; // simple adder and subtracter for the stack pointer
|
wire [DATA_SIZE:0] sp_plus_one; // simple adder and subtracter for the stack pointer
|
assign sp_plus_one = {1'b1, sp[7:0] + 8'b000000001};
|
assign sp_plus_one = {1'b1, sp[7:0] + 8'b000000001};
|
|
|
wire [DATA_SIZE:0] sp_minus_one;
|
wire [DATA_SIZE:0] sp_minus_one;
|
assign sp_minus_one = {1'b1, sp[7:0] - 8'b000000001};
|
assign sp_minus_one = {1'b1, sp[7:0] - 8'b000000001};
|
|
|
reg [ADDR_SIZE_:0] address_plus_index; // this two registers are used when the instruction uses indexing.
|
reg [ADDR_SIZE_:0] address_plus_index; // this two registers are used when the instruction uses indexing.
|
reg page_crossed; // address_plus_index always adds index to address and page_crossed asserts when the sum creates a carry.
|
reg page_crossed; // address_plus_index always adds index to address and page_crossed asserts when the sum creates a carry.
|
|
|
reg branch; // a simple reg that is asserted everytime a branch will be executed.
|
reg branch; // a simple reg that is asserted everytime a branch will be executed.
|
|
|
// this is the combinational logic related to indexed instructions
|
// this is the combinational logic related to indexed instructions
|
always @(*) begin
|
always @(*) begin
|
address_plus_index = 13'h000;
|
address_plus_index = 13'h000;
|
page_crossed = 1'b0;
|
page_crossed = 1'b0;
|
|
|
case (state)
|
case (state)
|
READ_MEM_FIX_ADDR, FETCH_HIGH_CALC_INDEX: begin
|
READ_MEM_FIX_ADDR, FETCH_HIGH_CALC_INDEX: begin
|
{page_crossed, address_plus_index[7:0]} = temp_addr[7:0] + index;
|
{page_crossed, address_plus_index[7:0]} = temp_addr[7:0] + index;
|
address_plus_index[12:8] = temp_addr[12:8] + page_crossed;
|
address_plus_index[12:8] = temp_addr[12:8] + page_crossed;
|
end
|
end
|
READ_FROM_POINTER_X1: begin
|
READ_FROM_POINTER_X1: begin
|
{page_crossed, address_plus_index[7:0]} = temp_addr[7:0] + index;
|
{page_crossed, address_plus_index[7:0]} = temp_addr[7:0] + index;
|
address_plus_index[12:8] = temp_addr[12:8];
|
address_plus_index[12:8] = data_in[4:0];
|
end
|
end
|
FETCH_OP_FIX_PC, FETCH_OP_EVAL_BRANCH: begin
|
FETCH_OP_FIX_PC, FETCH_OP_EVAL_BRANCH: begin
|
if (branch) begin
|
if (branch) begin
|
{page_crossed, address_plus_index[7:0]} = pc[7:0] + index;
|
{page_crossed, address_plus_index[7:0]} = pc[7:0] + index;
|
address_plus_index[12:8] = pc[12:8] + page_crossed;
|
address_plus_index[12:8] = pc[12:8] + page_crossed;
|
// warning: pc might feed these lines twice and cause branch failure
|
// warning: pc might feed these lines twice and cause branch failure
|
end // solution: add a temp reg i guess
|
end // solution: add a temp reg i guess
|
end
|
end
|
|
|
READ_FROM_POINTER: begin
|
READ_FROM_POINTER: begin
|
if (indirectx) begin
|
if (indirectx) begin
|
{page_crossed, address_plus_index[7:0]} = temp_data + index;
|
{page_crossed, address_plus_index[7:0]} = temp_data + index;
|
//address_plus_index[12:8] = 5'b00000; // already assigned earlier at this block
|
//address_plus_index[12:8] = 5'b00000; // already assigned earlier at this block
|
end
|
end
|
else if (jump_indirect) begin
|
else if (jump_indirect) begin
|
address_plus_index[7:0] = temp_addr[7:0] + 8'h01;
|
address_plus_index[7:0] = temp_addr[7:0] + 8'h01;
|
//address_plus_index[12:8] = 5'b00000;
|
//address_plus_index[12:8] = 5'b00000;
|
end
|
end
|
else begin // indirecty falls here
|
else begin // indirecty falls here
|
address_plus_index[7:0] = temp_data + 8'h01;
|
address_plus_index[7:0] = temp_data + 8'h01;
|
//address_plus_index[12:8] = 5'b00000;
|
//address_plus_index[12:8] = 5'b00000;
|
end
|
end
|
end
|
end
|
|
|
READ_FROM_POINTER_X: begin
|
READ_FROM_POINTER_X: begin
|
{page_crossed, address_plus_index[7:0]} = temp_data + index + 8'h01;
|
{page_crossed, address_plus_index[7:0]} = temp_data + index + 8'h01;
|
//address_plus_index[12:8] = 5'b00000;
|
//address_plus_index[12:8] = 5'b00000;
|
end
|
end
|
|
|
READ_MEM_CALC_INDEX: begin
|
READ_MEM_CALC_INDEX: begin
|
{page_crossed, address_plus_index[7:0]} = temp_addr[7:0] + index;
|
{page_crossed, address_plus_index[7:0]} = temp_addr[7:0] + index;
|
//address_plus_index[12:8] = 5'b00000;
|
//address_plus_index[12:8] = 5'b00000;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
reg [2:0] rst_counter; // a counter to preserve the cpu idle for six cycles
|
reg [2:0] rst_counter; // a counter to preserve the cpu idle for six cycles
|
|
|
always @ (posedge clk or negedge reset_n) begin // sequencial always block
|
always @ (posedge clk or negedge reset_n) begin // sequencial always block
|
if (reset_n == 1'b0) begin
|
if (reset_n == 1'b0) begin
|
// all registers must assume default values
|
// all registers must assume default values
|
pc <= 13'h0; // TODO: this is written somewhere. something about a reset vector. must be checked.
|
pc <= 13'h0; // TODO: this is written somewhere. something about a reset vector. must be checked.
|
sp <= 9'b111111111; // the default is 'h1FF
|
sp <= 9'b111111111; // the default is 'h1FF
|
ir <= 8'h00;
|
ir <= 8'h00;
|
temp_addr <= 13'h0000;
|
temp_addr <= 13'h0000;
|
temp_data <= 8'h00;
|
temp_data <= 8'h00;
|
state <= RESET;
|
state <= RESET;
|
// registered outputs also receive default values
|
// registered outputs also receive default values
|
address <= 13'h0000;
|
address <= 13'h0000;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
rst_counter <= 3'h0;
|
rst_counter <= 3'h0;
|
index <= 8'h00;
|
index <= 8'h00;
|
end
|
end
|
else begin
|
else begin
|
state <= next_state;
|
state <= next_state;
|
|
|
case (state)
|
case (state)
|
RESET: begin // The processor was reset
|
RESET: begin // The processor was reset
|
rst_counter <= rst_counter + 3'b001;
|
rst_counter <= rst_counter + 3'b001;
|
//sp <= 9'b111111111; // this prevents flipflops with different drivers
|
//sp <= 9'b111111111; // this prevents flipflops with different drivers
|
//$write("under reset");
|
//$write("under reset");
|
end
|
end
|
/*
|
/*
|
FETCH_OP: executed when the processor was reset or the last instruction could not fetch.
|
FETCH_OP: executed when the processor was reset or the last instruction could not fetch.
|
FETCH_OP_CALC_PARAM: enables the alu with an argument (alu_a) and fetchs the next instruction opcode. (pipelining)
|
FETCH_OP_CALC_PARAM: enables the alu with an argument (alu_a) and fetchs the next instruction opcode. (pipelining)
|
*/
|
*/
|
FETCH_OP, FETCH_OP_CALC_PARAM: begin // this is the pipeline happening!
|
FETCH_OP, FETCH_OP_CALC_PARAM: begin // this is the pipeline happening!
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= next_pc;
|
address <= next_pc;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
ir <= data_in;
|
ir <= data_in;
|
end
|
end
|
/*
|
/*
|
in this state the opcode is already known so truly execution begins.
|
in this state the opcode is already known so truly execution begins.
|
all instructions execute this cycle.
|
all instructions execute this cycle.
|
*/
|
*/
|
FETCH_LOW: begin
|
FETCH_LOW: begin
|
//$display("index_is_x = %b",index_is_x);
|
//$display("index_is_x = %b",index_is_x);
|
if (index_is_x == 1'b1) begin
|
if (index_is_x == 1'b1) begin
|
index <= alu_x;
|
index <= alu_x;
|
//$display("alu_x = %d",alu_x);
|
//$display("alu_x = %d",alu_x);
|
end
|
end
|
else begin
|
else begin
|
index <= alu_y;
|
index <= alu_y;
|
//$display("alu_y = %d",alu_y);
|
//$display("alu_y = %d",alu_y);
|
end
|
end
|
if (index_is_branch) begin
|
if (index_is_branch) begin
|
index <= temp_data;
|
index <= temp_data;
|
end
|
end
|
if (accumulator || implied || txs || tsx) begin
|
if (accumulator || implied || txs || tsx) begin
|
pc <= pc; // is this better?
|
pc <= pc; // is this better?
|
address <= pc;
|
address <= pc;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
|
|
if (txs) begin
|
if (txs) begin
|
sp[7:0] <= alu_x;
|
sp[7:0] <= alu_x;
|
end
|
end
|
//alu_a
|
//alu_a
|
end
|
end
|
else if (immediate || relative) begin
|
else if (immediate || relative) begin
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= next_pc;
|
address <= next_pc;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
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 || absolute_indexed || jump_indirect) begin
|
else if (absolute || absolute_indexed || jump_indirect) begin
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= next_pc;
|
address <= next_pc;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
temp_addr <= {{5{1'b0}},data_in};
|
temp_addr <= {{5{1'b0}},data_in};
|
temp_data <= 8'h00;
|
temp_data <= 8'h00;
|
end
|
end
|
else if (zero_page) begin
|
else if (zero_page) begin
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= {{5{1'b0}},data_in};
|
address <= {{5{1'b0}},data_in};
|
temp_addr <= {{5{1'b0}},data_in};
|
temp_addr <= {{5{1'b0}},data_in};
|
|
|
if (write) begin
|
if (write) begin
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
data_out <= alu_result;
|
data_out <= alu_result;
|
end
|
end
|
else begin
|
else begin
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
end
|
end
|
else if (zero_page_indexed) begin
|
else if (zero_page_indexed) begin
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= {{5{1'b0}}, data_in};
|
address <= {{5{1'b0}}, data_in};
|
temp_addr <= {{5{1'b0}}, data_in};
|
temp_addr <= {{5{1'b0}}, data_in};
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
end
|
end
|
else if (indirectx || indirecty) begin
|
else if (indirectx || indirecty) begin
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= data_in;
|
address <= data_in;
|
temp_data <= data_in;
|
temp_data <= data_in;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
end
|
end
|
else begin // the special instructions will fall here: BRK, RTI, RTS...
|
else begin // the special instructions will fall here: BRK, RTI, RTS...
|
if (brk) begin
|
if (brk) begin
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= sp;
|
address <= sp;
|
data_out <= {{3{1'b0}}, pc[12:8]};
|
data_out <= {{3{1'b0}}, pc[12:8]};
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
end
|
end
|
else if (rti || rts) begin
|
else if (rti || rts) begin
|
address <= sp;
|
address <= sp;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
end
|
end
|
else if (pha || php) begin
|
else if (pha || php) begin
|
pc <= pc;
|
pc <= pc;
|
address <= sp;
|
address <= sp;
|
data_out <= (pha) ? alu_result : alu_status;
|
data_out <= (pha) ? alu_result : alu_status;
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
end
|
end
|
else if (pla || plp) begin
|
else if (pla || plp) begin
|
pc <= pc;
|
pc <= pc;
|
address <= sp;
|
address <= sp;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
end
|
end
|
else begin // jsr
|
else begin // jsr
|
address <= sp;
|
address <= sp;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
temp_addr <= {{5{1'b0}}, data_in};
|
temp_addr <= {{5{1'b0}}, data_in};
|
pc <= next_pc;
|
pc <= next_pc;
|
end
|
end
|
end
|
end
|
end
|
end
|
FETCH_HIGH_CALC_INDEX: begin
|
FETCH_HIGH_CALC_INDEX: begin
|
pc <= next_pc;
|
pc <= next_pc;
|
temp_addr[12:8] <= data_in[4:0];
|
temp_addr[12:8] <= data_in[4:0];
|
address <= {data_in[4:0], address_plus_index[7:0]};
|
address <= {data_in[4:0], address_plus_index[7:0]};
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
// this cycle fetchs the next operand while still evaluating if a branch occurred.
|
// this cycle fetchs the next operand while still evaluating if a branch occurred.
|
FETCH_OP_EVAL_BRANCH: begin
|
FETCH_OP_EVAL_BRANCH: begin
|
if (branch) begin
|
if (branch) begin
|
pc <= {{5{1'b0}}, address_plus_index[7:0]};
|
pc <= {{5{1'b0}}, address_plus_index[7:0]};
|
address <= {{5{1'b0}}, address_plus_index[7:0]};
|
address <= {{5{1'b0}}, address_plus_index[7:0]};
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
else begin
|
else begin
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= next_pc;
|
address <= next_pc;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
ir <= data_in;
|
ir <= data_in;
|
end
|
end
|
end
|
end
|
// sometimes when reading memory page crosses may occur. the pc register must be fixed, i.e., add 16'h0100
|
// sometimes when reading memory page crosses may occur. the pc register must be fixed, i.e., add 16'h0100
|
FETCH_OP_FIX_PC: begin
|
FETCH_OP_FIX_PC: begin
|
if (page_crossed) begin
|
if (page_crossed) begin
|
pc[12:8] <= address_plus_index[12:8];
|
pc[12:8] <= address_plus_index[12:8];
|
address[12:8] <= address_plus_index[12:8];
|
address[12:8] <= address_plus_index[12:8];
|
end
|
end
|
else begin
|
else begin
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= next_pc;
|
address <= next_pc;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
ir <= data_in;
|
ir <= data_in;
|
end
|
end
|
end
|
end
|
// several instructions ocupy 3 bytes in memory. this cycle reads the third byte.
|
// several instructions ocupy 3 bytes in memory. this cycle reads the third byte.
|
FETCH_HIGH: begin
|
FETCH_HIGH: begin
|
if (jump) begin
|
if (jump) begin
|
pc <= {data_in[4:0], temp_addr[7:0]}; // PCL <= first byte, PCH <= second byte
|
pc <= {data_in[4:0], temp_addr[7:0]}; // PCL <= first byte, PCH <= second byte
|
address <= {data_in[4:0], temp_addr[7:0]};
|
address <= {data_in[4:0], temp_addr[7:0]};
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
else begin
|
else begin
|
if (write) begin
|
if (write) begin
|
pc <= next_pc;
|
pc <= next_pc;
|
temp_addr[12:8] <= data_in[4:0];
|
temp_addr[12:8] <= data_in[4:0];
|
address <= {data_in[4:0],temp_addr[7:0]};
|
address <= {data_in[4:0],temp_addr[7:0]};
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
data_out <= alu_result;
|
data_out <= alu_result;
|
end
|
end
|
else begin // read_modify_write or just read
|
else begin // read_modify_write or just read
|
pc <= next_pc;
|
pc <= next_pc;
|
temp_addr[12:8] <= data_in[4:0];
|
temp_addr[12:8] <= data_in[4:0];
|
address <= {data_in[4:0],temp_addr[7:0]};
|
address <= {data_in[4:0],temp_addr[7:0]};
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
end
|
end
|
end
|
end
|
// read memory at address
|
// read memory at address
|
READ_MEM: begin
|
READ_MEM: begin
|
if (read_modify_write) begin
|
if (read_modify_write) begin
|
pc <= pc;
|
pc <= pc;
|
address <= temp_addr;
|
address <= temp_addr;
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
temp_data <= data_in;
|
temp_data <= data_in;
|
data_out <= data_in; // writeback the same value
|
data_out <= data_in; // writeback the same value
|
end
|
end
|
else begin
|
else begin
|
pc <= pc;
|
pc <= pc;
|
address <= pc;
|
address <= pc;
|
temp_data <= data_in;
|
temp_data <= data_in;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
end
|
end
|
READ_MEM_CALC_INDEX: begin
|
READ_MEM_CALC_INDEX: begin
|
address <= address_plus_index;
|
address <= address_plus_index;
|
temp_addr <= address_plus_index;
|
temp_addr <= address_plus_index;
|
|
|
if (write) begin
|
if (write) begin
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
data_out <= alu_result;
|
data_out <= alu_result;
|
end
|
end
|
else begin
|
else begin
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
|
|
end
|
end
|
READ_MEM_FIX_ADDR: begin
|
READ_MEM_FIX_ADDR: begin
|
if (read) begin
|
if (read) begin
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
|
|
if (page_crossed) begin // fix address
|
if (page_crossed) begin // fix address
|
address <= address_plus_index;
|
address <= address_plus_index;
|
temp_addr <= address_plus_index;
|
temp_addr <= address_plus_index;
|
end
|
end
|
else begin
|
else begin
|
address <= pc;
|
address <= pc;
|
temp_data <= data_in;
|
temp_data <= data_in;
|
end
|
end
|
end
|
end
|
else if (write) begin
|
else if (write) begin
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
data_out <= alu_result;
|
data_out <= alu_result;
|
address <= address_plus_index;
|
address <= address_plus_index;
|
temp_addr <= address_plus_index;
|
temp_addr <= address_plus_index;
|
|
|
end
|
end
|
else begin // read modify write
|
else begin // read modify write
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
address <= address_plus_index;
|
address <= address_plus_index;
|
temp_addr <= address_plus_index;
|
temp_addr <= address_plus_index;
|
end
|
end
|
end
|
end
|
// some instructions have a dummy write cycle. this is it.
|
// some instructions have a dummy write cycle. this is it.
|
DUMMY_WRT_CALC: begin
|
DUMMY_WRT_CALC: begin
|
pc <= pc;
|
pc <= pc;
|
address <= temp_addr;
|
address <= temp_addr;
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
data_out <= alu_result;
|
data_out <= alu_result;
|
end
|
end
|
WRITE_MEM: begin
|
WRITE_MEM: begin
|
pc <= pc;
|
pc <= pc;
|
address <= pc;
|
address <= pc;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
READ_FROM_POINTER: begin
|
READ_FROM_POINTER: begin
|
if (jump_indirect) begin
|
if (jump_indirect) begin
|
pc[7:0] <= data_in;
|
pc[7:0] <= data_in;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
address <= address_plus_index;
|
address <= address_plus_index;
|
end
|
end
|
else begin
|
else begin
|
pc <= pc;
|
pc <= pc;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
|
|
if (indirectx) begin
|
if (indirectx) begin
|
address <= address_plus_index;
|
address <= address_plus_index;
|
end
|
end
|
else begin // indirecty falls here
|
else begin // indirecty falls here
|
address <= address_plus_index;
|
address <= address_plus_index;
|
temp_addr <= {{5{1'b0}}, data_in};
|
temp_addr <= {{5{1'b0}}, data_in};
|
end
|
end
|
end
|
end
|
end
|
end
|
READ_FROM_POINTER_X: begin
|
READ_FROM_POINTER_X: begin
|
pc <= pc;
|
pc <= pc;
|
address <= address_plus_index;
|
address <= address_plus_index;
|
temp_addr[7:0] <= data_in;
|
temp_addr[7:0] <= data_in;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
end
|
end
|
READ_FROM_POINTER_X1: begin
|
READ_FROM_POINTER_X1: begin
|
if (jump_indirect) begin
|
if (jump_indirect) begin
|
pc[12:8] <= data_in[4:0];
|
pc[12:8] <= data_in[4:0];
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
address <= {data_in[4:0], pc[7:0]};
|
address <= {data_in[4:0], pc[7:0]};
|
end
|
end
|
else if (indirectx) begin
|
else if (indirectx) begin
|
address <= {data_in[4:0], temp_addr[7:0]};
|
address <= {data_in[4:0], temp_addr[7:0]};
|
if (write) begin
|
if (write) begin
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
data_out <= alu_result;
|
data_out <= alu_result;
|
end
|
end
|
else begin
|
else begin
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
end
|
end
|
end
|
end
|
else begin // indirecty falls here
|
else begin // indirecty falls here
|
address <= address_plus_index;
|
address <= address_plus_index;
|
temp_addr[12:8] <= data_in;
|
temp_addr[12:8] <= data_in;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
end
|
end
|
end
|
end
|
PUSH_PCH: begin
|
PUSH_PCH: begin
|
pc <= pc;
|
pc <= pc;
|
address <= sp_minus_one;
|
address <= sp_minus_one;
|
data_out <= pc[7:0];
|
data_out <= pc[7:0];
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
sp <= sp_minus_one;
|
sp <= sp_minus_one;
|
end
|
end
|
PUSH_PCL: begin
|
PUSH_PCL: begin
|
if (jsr) begin
|
if (jsr) begin
|
pc <= pc;
|
pc <= pc;
|
address <= pc;
|
address <= pc;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
sp <= sp_minus_one;
|
sp <= sp_minus_one;
|
end
|
end
|
else begin
|
else begin
|
pc <= pc;
|
pc <= pc;
|
address <= sp_minus_one;
|
address <= sp_minus_one;
|
data_out <= alu_status;
|
data_out <= alu_status;
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
sp <= sp_minus_one;
|
sp <= sp_minus_one;
|
end
|
end
|
end
|
end
|
PUSH_STATUS: begin
|
PUSH_STATUS: begin
|
address <= 13'h1FFE;
|
address <= 13'h1FFE;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
sp <= sp_minus_one;
|
sp <= sp_minus_one;
|
end
|
end
|
FETCH_PCL: begin
|
FETCH_PCL: begin
|
pc[7:0] <= data_in;
|
pc[7:0] <= data_in;
|
address <= 13'h1FFF;
|
address <= 13'h1FFF;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
end
|
end
|
FETCH_PCH: begin
|
FETCH_PCH: begin
|
pc[12:8] <= data_in[4:0];
|
pc[12:8] <= data_in[4:0];
|
address <= {data_in[4:0], pc[7:0]};
|
address <= {data_in[4:0], pc[7:0]};
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
end
|
end
|
INCREMENT_SP: begin
|
INCREMENT_SP: begin
|
sp <= sp_plus_one;
|
sp <= sp_plus_one;
|
address <= sp_plus_one;
|
address <= sp_plus_one;
|
end
|
end
|
PULL_STATUS: begin
|
PULL_STATUS: begin
|
sp <= sp_plus_one;
|
sp <= sp_plus_one;
|
address <= sp_plus_one;
|
address <= sp_plus_one;
|
temp_data <= data_in;
|
temp_data <= data_in;
|
end
|
end
|
PULL_PCL: begin
|
PULL_PCL: begin
|
sp <= sp_plus_one;
|
sp <= sp_plus_one;
|
address <= sp_plus_one;
|
address <= sp_plus_one;
|
pc[7:0] <= data_in;
|
pc[7:0] <= data_in;
|
end
|
end
|
PULL_PCH: begin
|
PULL_PCH: begin
|
pc[12:8] <= data_in[4:0];
|
pc[12:8] <= data_in[4:0];
|
address <= {data_in[4:0], pc[7:0]};
|
address <= {data_in[4:0], pc[7:0]};
|
end
|
end
|
INCREMENT_PC: begin
|
INCREMENT_PC: begin
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= next_pc;
|
address <= next_pc;
|
end
|
end
|
PUSH_REGISTER: begin
|
PUSH_REGISTER: begin
|
pc <= pc;
|
pc <= pc;
|
address <= pc;
|
address <= pc;
|
sp <= sp_minus_one;
|
sp <= sp_minus_one;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
temp_data <= data_in;
|
temp_data <= data_in;
|
end
|
end
|
PULL_REGISTER: begin
|
PULL_REGISTER: begin
|
pc <= pc;
|
pc <= pc;
|
address <= pc;
|
address <= pc;
|
temp_data <= data_in;
|
temp_data <= data_in;
|
end
|
end
|
DUMMY: begin
|
DUMMY: begin
|
address <= sp;
|
address <= sp;
|
mem_rw <= MEM_WRITE;
|
mem_rw <= MEM_WRITE;
|
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 and the combinational output logic always block
|
always @ (*) begin // this is the next_state logic and the combinational output logic always block
|
alu_opcode = 8'h00;
|
alu_opcode = 8'h00;
|
alu_a = 8'h00;
|
alu_a = 8'h00;
|
alu_enable = 1'b0;
|
alu_enable = 1'b0;
|
next_state = RESET; // these lines prevents latches
|
next_state = RESET; // these lines prevents latches
|
|
|
case (state)
|
case (state)
|
RESET: begin
|
RESET: begin
|
if (rst_counter == 3'd6) begin
|
if (rst_counter == 3'd6) begin
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
end
|
end
|
end
|
end
|
FETCH_OP: begin
|
FETCH_OP: begin
|
next_state = FETCH_LOW;
|
next_state = FETCH_LOW;
|
end
|
end
|
FETCH_OP_CALC_PARAM: begin
|
FETCH_OP_CALC_PARAM: begin
|
next_state = FETCH_LOW;
|
next_state = FETCH_LOW;
|
alu_opcode = ir;
|
alu_opcode = ir;
|
alu_enable = 1'b1;
|
alu_enable = 1'b1;
|
alu_a = temp_data;
|
alu_a = temp_data;
|
end
|
end
|
FETCH_LOW: begin
|
FETCH_LOW: begin
|
if (accumulator || implied || txs) begin
|
if (accumulator || implied || txs) begin
|
if (!nop) begin
|
if (!nop) begin
|
alu_opcode = ir;
|
alu_opcode = ir;
|
alu_enable = 1'b1;
|
alu_enable = 1'b1;
|
end
|
end
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
end
|
end
|
else if (tsx) begin
|
else if (tsx) begin
|
alu_opcode = ir;
|
alu_opcode = ir;
|
alu_enable = 1'b1;
|
alu_enable = 1'b1;
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
alu_a = sp[7:0];
|
alu_a = sp[7:0];
|
end
|
end
|
else if (immediate) begin
|
else if (immediate) begin
|
next_state = FETCH_OP_CALC_PARAM;
|
next_state = FETCH_OP_CALC_PARAM;
|
end
|
end
|
else if (zero_page) begin
|
else if (zero_page) begin
|
if (read || read_modify_write) begin
|
if (read || read_modify_write) begin
|
next_state = READ_MEM;
|
next_state = READ_MEM;
|
end
|
end
|
else if (write) begin
|
else if (write) begin
|
next_state = WRITE_MEM;
|
next_state = WRITE_MEM;
|
alu_opcode = ir;
|
alu_opcode = ir;
|
alu_enable = 1'b1;
|
alu_enable = 1'b1;
|
alu_a = 8'h00;
|
alu_a = 8'h00;
|
end
|
end
|
else begin
|
else begin
|
//$write("unknown behavior");
|
//$write("unknown behavior");
|
//$finish(0);
|
//$finish(0);
|
end
|
end
|
end
|
end
|
else if (zero_page_indexed) begin
|
else if (zero_page_indexed) begin
|
next_state = READ_MEM_CALC_INDEX;
|
next_state = READ_MEM_CALC_INDEX;
|
end
|
end
|
else if (absolute || jump_indirect) begin
|
else if (absolute || jump_indirect) begin
|
next_state = FETCH_HIGH;
|
next_state = FETCH_HIGH;
|
if (write) begin // this is being done one cycle early but i have checked and the ALU will still work properly
|
if (write) begin // this is being done one cycle early but i have checked and the ALU will still work properly
|
alu_opcode = ir;
|
alu_opcode = ir;
|
alu_enable = 1'b1;
|
alu_enable = 1'b1;
|
alu_a = 8'h00;
|
alu_a = 8'h00;
|
end
|
end
|
end
|
end
|
else if (absolute_indexed) begin
|
else if (absolute_indexed) begin
|
next_state = FETCH_HIGH_CALC_INDEX;
|
next_state = FETCH_HIGH_CALC_INDEX;
|
end
|
end
|
else if (relative) begin
|
else if (relative) begin
|
next_state = FETCH_OP_EVAL_BRANCH;
|
next_state = FETCH_OP_EVAL_BRANCH;
|
end
|
end
|
else if (indirectx || indirecty) begin
|
else if (indirectx || indirecty) begin
|
next_state = READ_FROM_POINTER;
|
next_state = READ_FROM_POINTER;
|
end
|
end
|
else begin // all the special instructions will fall here
|
else begin // all the special instructions will fall here
|
if (brk) begin
|
if (brk) begin
|
next_state = PUSH_PCH;
|
next_state = PUSH_PCH;
|
end
|
end
|
else if (rti || rts) begin
|
else if (rti || rts) begin
|
next_state = INCREMENT_SP;
|
next_state = INCREMENT_SP;
|
end
|
end
|
else if (pha) begin
|
else if (pha) begin
|
alu_opcode = ir;
|
alu_opcode = ir;
|
alu_enable = 1'b1;
|
alu_enable = 1'b1;
|
//alu_a = 8'h00;
|
//alu_a = 8'h00;
|
next_state = PUSH_REGISTER;
|
next_state = PUSH_REGISTER;
|
end
|
end
|
else if (php) begin
|
else if (php) begin
|
next_state = PUSH_REGISTER;
|
next_state = PUSH_REGISTER;
|
end
|
end
|
else if (pla || plp) begin
|
else if (pla || plp) begin
|
next_state = INCREMENT_SP;
|
next_state = INCREMENT_SP;
|
end
|
end
|
else begin // jsr
|
else begin // jsr
|
next_state = DUMMY;
|
next_state = DUMMY;
|
end
|
end
|
end
|
end
|
end
|
end
|
READ_FROM_POINTER: begin
|
READ_FROM_POINTER: begin
|
if (indirectx) begin
|
if (indirectx) begin
|
next_state = READ_FROM_POINTER_X;
|
next_state = READ_FROM_POINTER_X;
|
end
|
end
|
else begin // indirecty and jump indirect falls here
|
else begin // indirecty and jump indirect falls here
|
next_state = READ_FROM_POINTER_X1;
|
next_state = READ_FROM_POINTER_X1;
|
end
|
end
|
end
|
end
|
READ_FROM_POINTER_X: begin
|
READ_FROM_POINTER_X: begin
|
next_state = READ_FROM_POINTER_X1;
|
next_state = READ_FROM_POINTER_X1;
|
end
|
end
|
READ_FROM_POINTER_X1: begin
|
READ_FROM_POINTER_X1: begin
|
if (jump_indirect) begin
|
if (jump_indirect) begin
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
end
|
end
|
else if (indirecty) begin
|
else if (indirecty) begin
|
next_state = READ_MEM_FIX_ADDR;
|
next_state = READ_MEM_FIX_ADDR;
|
end
|
end
|
else begin
|
else begin
|
if (read) begin // no instruction using pointers is from type read_modify_write
|
if (read) begin // no instruction using pointers is from type read_modify_write
|
next_state = READ_MEM;
|
next_state = READ_MEM;
|
end
|
end
|
else if (write) begin
|
else if (write) begin
|
alu_opcode = ir;
|
alu_opcode = ir;
|
alu_enable = 1'b1;
|
alu_enable = 1'b1;
|
next_state = WRITE_MEM;
|
next_state = WRITE_MEM;
|
end
|
end
|
end
|
end
|
end
|
end
|
FETCH_OP_EVAL_BRANCH: begin
|
FETCH_OP_EVAL_BRANCH: begin
|
if (branch) begin
|
if (branch) begin
|
next_state = FETCH_OP_FIX_PC;
|
next_state = FETCH_OP_FIX_PC;
|
end
|
end
|
else begin
|
else begin
|
next_state = FETCH_LOW;
|
next_state = FETCH_LOW;
|
end
|
end
|
end
|
end
|
FETCH_OP_FIX_PC: begin
|
FETCH_OP_FIX_PC: begin
|
if (page_crossed) begin
|
if (page_crossed) begin
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
end
|
end
|
else begin
|
else begin
|
next_state = FETCH_LOW;
|
next_state = FETCH_LOW;
|
end
|
end
|
end
|
end
|
FETCH_HIGH_CALC_INDEX: begin
|
FETCH_HIGH_CALC_INDEX: begin
|
next_state = READ_MEM_FIX_ADDR;
|
next_state = READ_MEM_FIX_ADDR;
|
end
|
end
|
READ_MEM_FIX_ADDR: begin
|
READ_MEM_FIX_ADDR: begin
|
if (read) begin
|
if (read) begin
|
if (page_crossed) begin
|
if (page_crossed) begin
|
next_state = READ_MEM;
|
next_state = READ_MEM;
|
end
|
end
|
else begin
|
else begin
|
next_state = FETCH_OP_CALC_PARAM;
|
next_state = FETCH_OP_CALC_PARAM;
|
end
|
end
|
end
|
end
|
else if (read_modify_write) begin
|
else if (read_modify_write) begin
|
next_state = READ_MEM;
|
next_state = READ_MEM;
|
end
|
end
|
else if (write) begin
|
else if (write) begin
|
next_state = WRITE_MEM;
|
next_state = WRITE_MEM;
|
alu_enable = 1'b1;
|
alu_enable = 1'b1;
|
alu_opcode = ir;
|
alu_opcode = ir;
|
end
|
end
|
else begin
|
else begin
|
//$write("unknown behavior");
|
//$write("unknown behavior");
|
//$finish(0);
|
//$finish(0);
|
end
|
end
|
end
|
end
|
FETCH_HIGH: begin
|
FETCH_HIGH: begin
|
if (jump_indirect) begin
|
if (jump_indirect) begin
|
next_state = READ_FROM_POINTER;
|
next_state = READ_FROM_POINTER;
|
end
|
end
|
else if (jump) begin
|
else if (jump) begin
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
end
|
end
|
else if (read || read_modify_write) begin
|
else if (read || read_modify_write) begin
|
next_state = READ_MEM;
|
next_state = READ_MEM;
|
end
|
end
|
else if (write) begin
|
else if (write) begin
|
next_state = WRITE_MEM;
|
next_state = WRITE_MEM;
|
end
|
end
|
else begin
|
else begin
|
//$write("unknown behavior");
|
//$write("unknown behavior");
|
//$finish(0);
|
//$finish(0);
|
end
|
end
|
end
|
end
|
READ_MEM_CALC_INDEX: begin
|
READ_MEM_CALC_INDEX: begin
|
if (read || read_modify_write) begin
|
if (read || read_modify_write) begin
|
next_state = READ_MEM;
|
next_state = READ_MEM;
|
end
|
end
|
else if (write) begin
|
else if (write) begin
|
alu_opcode = ir;
|
alu_opcode = ir;
|
alu_enable = 1'b1;
|
alu_enable = 1'b1;
|
next_state = WRITE_MEM;
|
next_state = WRITE_MEM;
|
end
|
end
|
else begin
|
else begin
|
//$write("unknown behavior");
|
//$write("unknown behavior");
|
//$finish(0);
|
//$finish(0);
|
end
|
end
|
end
|
end
|
READ_MEM: begin
|
READ_MEM: begin
|
if (read) begin
|
if (read) begin
|
next_state = FETCH_OP_CALC_PARAM;
|
next_state = FETCH_OP_CALC_PARAM;
|
end
|
end
|
else if (read_modify_write) begin
|
else if (read_modify_write) begin
|
next_state = DUMMY_WRT_CALC;
|
next_state = DUMMY_WRT_CALC;
|
end
|
end
|
end
|
end
|
DUMMY_WRT_CALC: begin
|
DUMMY_WRT_CALC: begin
|
alu_opcode = ir;
|
alu_opcode = ir;
|
alu_enable = 1'b1;
|
alu_enable = 1'b1;
|
alu_a = data_in;
|
alu_a = data_in;
|
next_state = WRITE_MEM;
|
next_state = WRITE_MEM;
|
end
|
end
|
WRITE_MEM: begin
|
WRITE_MEM: begin
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
end
|
end
|
PUSH_PCH: begin
|
PUSH_PCH: begin
|
next_state = PUSH_PCL;
|
next_state = PUSH_PCL;
|
end
|
end
|
PUSH_PCL: begin
|
PUSH_PCL: begin
|
if (jsr) begin
|
if (jsr) begin
|
next_state = FETCH_HIGH;
|
next_state = FETCH_HIGH;
|
end
|
end
|
else begin
|
else begin
|
next_state = PUSH_STATUS;
|
next_state = PUSH_STATUS;
|
end
|
end
|
end
|
end
|
PUSH_STATUS: begin
|
PUSH_STATUS: begin
|
next_state = FETCH_PCL;
|
next_state = FETCH_PCL;
|
end
|
end
|
FETCH_PCL: begin
|
FETCH_PCL: begin
|
next_state = FETCH_PCH;
|
next_state = FETCH_PCH;
|
end
|
end
|
FETCH_PCH: begin
|
FETCH_PCH: begin
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
end
|
end
|
INCREMENT_SP: begin
|
INCREMENT_SP: begin
|
if (rti) begin
|
if (rti) begin
|
next_state = PULL_STATUS;
|
next_state = PULL_STATUS;
|
end
|
end
|
else if (pla || plp) begin
|
else if (pla || plp) begin
|
next_state = PULL_REGISTER;
|
next_state = PULL_REGISTER;
|
end
|
end
|
else begin // rts
|
else begin // rts
|
next_state = PULL_PCL;
|
next_state = PULL_PCL;
|
end
|
end
|
end
|
end
|
PULL_STATUS: begin
|
PULL_STATUS: begin
|
next_state = PULL_PCL;
|
next_state = PULL_PCL;
|
end
|
end
|
PULL_PCL: begin
|
PULL_PCL: begin
|
next_state = PULL_PCH;
|
next_state = PULL_PCH;
|
|
|
if (rti) begin
|
if (rti) begin
|
alu_opcode = ir;
|
alu_opcode = ir;
|
alu_enable = 1'b1;
|
alu_enable = 1'b1;
|
alu_a = temp_data;
|
alu_a = temp_data;
|
end
|
end
|
end
|
end
|
PULL_PCH: begin
|
PULL_PCH: begin
|
if (rti) begin
|
if (rti) begin
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
end
|
end
|
else begin // rts
|
else begin // rts
|
next_state = INCREMENT_PC;
|
next_state = INCREMENT_PC;
|
end
|
end
|
end
|
end
|
INCREMENT_PC: begin
|
INCREMENT_PC: begin
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
end
|
end
|
PUSH_REGISTER: begin
|
PUSH_REGISTER: begin
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
end
|
end
|
PULL_REGISTER: begin
|
PULL_REGISTER: begin
|
next_state = FETCH_OP_CALC_PARAM;
|
next_state = FETCH_OP_CALC_PARAM;
|
end
|
end
|
DUMMY: begin
|
DUMMY: begin
|
next_state = PUSH_PCH;
|
next_state = PUSH_PCH;
|
end
|
end
|
default: begin
|
default: begin
|
next_state = RESET;
|
next_state = RESET;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
// this always block is responsible for updating the address mode and the type of operation being done
|
// this always block is responsible for updating the address mode and the type of operation being done
|
always @ (*) begin //
|
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;
|
indirectx = 1'b0;
|
indirectx = 1'b0;
|
indirecty = 1'b0;
|
indirecty = 1'b0;
|
relative = 1'b0;
|
relative = 1'b0;
|
zero_page = 1'b0;
|
zero_page = 1'b0;
|
zero_page_indexed = 1'b0;
|
zero_page_indexed = 1'b0;
|
//index_is_x = 1'b1;
|
//index_is_x = 1'b1;
|
index_is_branch = 1'b0;
|
index_is_branch = 1'b0;
|
|
|
//index = 8'h00;
|
//index = 8'h00;
|
|
|
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;
|
jump_indirect = 1'b0;
|
jump_indirect = 1'b0;
|
branch = 1'b0;
|
branch = 1'b0;
|
|
|
brk = 1'b0;
|
brk = 1'b0;
|
rti = 1'b0;
|
rti = 1'b0;
|
rts = 1'b0;
|
rts = 1'b0;
|
pha = 1'b0;
|
pha = 1'b0;
|
php = 1'b0;
|
php = 1'b0;
|
pla = 1'b0;
|
pla = 1'b0;
|
plp = 1'b0;
|
plp = 1'b0;
|
jsr = 1'b0;
|
jsr = 1'b0;
|
tsx = 1'b0;
|
tsx = 1'b0;
|
txs = 1'b0;
|
txs = 1'b0;
|
nop = 1'b0;
|
nop = 1'b0;
|
|
|
case (ir)
|
case (ir)
|
CLC_IMP, CLD_IMP, CLI_IMP, CLV_IMP, DEX_IMP, DEY_IMP, INX_IMP, INY_IMP, SEC_IMP, SED_IMP, SEI_IMP, TAX_IMP,
|
CLC_IMP, CLD_IMP, CLI_IMP, CLV_IMP, DEX_IMP, DEY_IMP, INX_IMP, INY_IMP, SEC_IMP, SED_IMP, SEI_IMP, TAX_IMP,
|
TAY_IMP, TXA_IMP, TYA_IMP: begin
|
TAY_IMP, TXA_IMP, TYA_IMP: begin
|
implied = 1'b1;
|
implied = 1'b1;
|
end
|
end
|
NOP_IMP: begin
|
NOP_IMP: begin
|
implied = 1'b1;
|
implied = 1'b1;
|
nop = 1'b1;
|
nop = 1'b1;
|
end
|
end
|
ASL_ACC, LSR_ACC, ROL_ACC, ROR_ACC: begin
|
ASL_ACC, LSR_ACC, ROL_ACC, ROR_ACC: begin
|
accumulator = 1'b1;
|
accumulator = 1'b1;
|
end
|
end
|
ADC_IMM, AND_IMM, CMP_IMM, CPX_IMM, CPY_IMM, EOR_IMM, LDA_IMM, LDX_IMM, LDY_IMM, ORA_IMM, SBC_IMM: begin
|
ADC_IMM, AND_IMM, CMP_IMM, CPX_IMM, CPY_IMM, EOR_IMM, LDA_IMM, LDX_IMM, LDY_IMM, ORA_IMM, SBC_IMM: begin
|
immediate = 1'b1;
|
immediate = 1'b1;
|
end
|
end
|
ADC_ZPG, AND_ZPG, ASL_ZPG, BIT_ZPG, CMP_ZPG, CPX_ZPG, CPY_ZPG, DEC_ZPG, EOR_ZPG, INC_ZPG, LDA_ZPG, LDX_ZPG, LDY_ZPG,
|
ADC_ZPG, AND_ZPG, ASL_ZPG, BIT_ZPG, CMP_ZPG, CPX_ZPG, CPY_ZPG, DEC_ZPG, EOR_ZPG, INC_ZPG, LDA_ZPG, LDX_ZPG, LDY_ZPG,
|
LSR_ZPG, ORA_ZPG, ROL_ZPG, ROR_ZPG, SBC_ZPG, STA_ZPG, STX_ZPG, STY_ZPG: begin
|
LSR_ZPG, ORA_ZPG, ROL_ZPG, ROR_ZPG, SBC_ZPG, STA_ZPG, STX_ZPG, STY_ZPG: begin
|
zero_page = 1'b1;
|
zero_page = 1'b1;
|
end
|
end
|
ADC_ZPX, AND_ZPX, ASL_ZPX, CMP_ZPX, DEC_ZPX, EOR_ZPX, INC_ZPX, LDA_ZPX, LDY_ZPX, LSR_ZPX, ORA_ZPX, ROL_ZPX, ROR_ZPX,
|
ADC_ZPX, AND_ZPX, ASL_ZPX, CMP_ZPX, DEC_ZPX, EOR_ZPX, INC_ZPX, LDA_ZPX, LDY_ZPX, LSR_ZPX, ORA_ZPX, ROL_ZPX, ROR_ZPX,
|
SBC_ZPX, STA_ZPX, STY_ZPX: begin
|
SBC_ZPX, STA_ZPX, STY_ZPX: begin
|
zero_page_indexed = 1'b1;
|
zero_page_indexed = 1'b1;
|
index_is_x = 1'b1;
|
index_is_x = 1'b1;
|
//index = alu_x;
|
//index = alu_x;
|
end
|
end
|
LDX_ZPY, STX_ZPY: begin
|
LDX_ZPY, STX_ZPY: begin
|
zero_page_indexed = 1'b1;
|
zero_page_indexed = 1'b1;
|
index_is_x = 1'b0;
|
index_is_x = 1'b0;
|
//index = alu_y;
|
//index = alu_y;
|
end
|
end
|
BCC_REL: begin
|
BCC_REL: begin
|
relative = 1'b1;
|
relative = 1'b1;
|
index_is_branch = 1'b1;
|
index_is_branch = 1'b1;
|
//index = temp_data;
|
//index = temp_data;
|
|
|
if (!alu_status[C]) begin
|
if (!alu_status[C]) begin
|
branch = 1'b1;
|
branch = 1'b1;
|
end
|
end
|
else begin
|
else begin
|
branch = 1'b0;
|
branch = 1'b0;
|
end
|
end
|
end
|
end
|
BCS_REL: begin
|
BCS_REL: begin
|
relative = 1'b1;
|
relative = 1'b1;
|
index_is_branch = 1'b1;
|
index_is_branch = 1'b1;
|
//index = temp_data;
|
//index = temp_data;
|
|
|
if (alu_status[C]) begin
|
if (alu_status[C]) begin
|
branch = 1'b1;
|
branch = 1'b1;
|
end
|
end
|
else begin
|
else begin
|
branch = 1'b0;
|
branch = 1'b0;
|
end
|
end
|
end
|
end
|
BEQ_REL: begin
|
BEQ_REL: begin
|
relative = 1'b1;
|
relative = 1'b1;
|
index_is_branch = 1'b1;
|
index_is_branch = 1'b1;
|
//index = temp_data;
|
//index = temp_data;
|
|
|
if (alu_status[Z]) begin
|
if (alu_status[Z]) begin
|
branch = 1'b1;
|
branch = 1'b1;
|
end
|
end
|
else begin
|
else begin
|
branch = 1'b0;
|
branch = 1'b0;
|
end
|
end
|
end
|
end
|
BNE_REL: begin
|
BNE_REL: begin
|
relative = 1'b1;
|
relative = 1'b1;
|
index_is_branch = 1'b1;
|
index_is_branch = 1'b1;
|
//index = temp_data;
|
//index = temp_data;
|
|
|
if (alu_status[Z] == 1'b0) begin
|
if (alu_status[Z] == 1'b0) begin
|
branch = 1'b1;
|
branch = 1'b1;
|
end
|
end
|
else begin
|
else begin
|
branch = 1'b0;
|
branch = 1'b0;
|
end
|
end
|
end
|
end
|
BPL_REL: begin
|
BPL_REL: begin
|
relative = 1'b1;
|
relative = 1'b1;
|
index_is_branch = 1'b1;
|
index_is_branch = 1'b1;
|
//index = temp_data;
|
//index = temp_data;
|
|
|
if (!alu_status[N]) begin
|
if (!alu_status[N]) begin
|
branch = 1'b1;
|
branch = 1'b1;
|
end
|
end
|
else begin
|
else begin
|
branch = 1'b0;
|
branch = 1'b0;
|
end
|
end
|
end
|
end
|
BMI_REL: begin
|
BMI_REL: begin
|
relative = 1'b1;
|
relative = 1'b1;
|
index_is_branch = 1'b1;
|
index_is_branch = 1'b1;
|
//index = temp_data;
|
//index = temp_data;
|
|
|
if (alu_status[N]) begin
|
if (alu_status[N]) begin
|
branch = 1'b1;
|
branch = 1'b1;
|
end
|
end
|
else begin
|
else begin
|
branch = 1'b0;
|
branch = 1'b0;
|
end
|
end
|
end
|
end
|
BVC_REL: begin
|
BVC_REL: begin
|
relative = 1'b1;
|
relative = 1'b1;
|
index_is_branch = 1'b1;
|
index_is_branch = 1'b1;
|
//index = temp_data;
|
//index = temp_data;
|
|
|
if (!alu_status[V]) begin
|
if (!alu_status[V]) begin
|
branch = 1'b1;
|
branch = 1'b1;
|
end
|
end
|
else begin
|
else begin
|
branch = 1'b0;
|
branch = 1'b0;
|
end
|
end
|
end
|
end
|
BVS_REL: begin
|
BVS_REL: begin
|
relative = 1'b1;
|
relative = 1'b1;
|
index_is_branch = 1'b1;
|
index_is_branch = 1'b1;
|
//index = temp_data;
|
//index = temp_data;
|
|
|
if (alu_status[V]) begin
|
if (alu_status[V]) begin
|
branch = 1'b1;
|
branch = 1'b1;
|
end
|
end
|
else begin
|
else begin
|
branch = 1'b0;
|
branch = 1'b0;
|
end
|
end
|
end
|
end
|
ADC_ABS, AND_ABS, ASL_ABS, BIT_ABS, CMP_ABS, CPX_ABS, CPY_ABS, DEC_ABS, EOR_ABS, INC_ABS, LDA_ABS,
|
ADC_ABS, AND_ABS, ASL_ABS, BIT_ABS, CMP_ABS, CPX_ABS, CPY_ABS, DEC_ABS, EOR_ABS, INC_ABS, LDA_ABS,
|
LDX_ABS, LDY_ABS, LSR_ABS, ORA_ABS, ROL_ABS, ROR_ABS, SBC_ABS, STA_ABS, STX_ABS, STY_ABS: begin
|
LDX_ABS, LDY_ABS, LSR_ABS, ORA_ABS, ROL_ABS, ROR_ABS, SBC_ABS, STA_ABS, STX_ABS, STY_ABS: begin
|
absolute = 1'b1;
|
absolute = 1'b1;
|
end
|
end
|
ADC_ABX, AND_ABX, ASL_ABX, CMP_ABX, DEC_ABX, EOR_ABX, INC_ABX, LDA_ABX, LDY_ABX, LSR_ABX, ORA_ABX, ROL_ABX, ROR_ABX,
|
ADC_ABX, AND_ABX, ASL_ABX, CMP_ABX, DEC_ABX, EOR_ABX, INC_ABX, LDA_ABX, LDY_ABX, LSR_ABX, ORA_ABX, ROL_ABX, ROR_ABX,
|
SBC_ABX, STA_ABX: begin
|
SBC_ABX, STA_ABX: begin
|
absolute_indexed = 1'b1;
|
absolute_indexed = 1'b1;
|
index_is_x = 1'b1;
|
index_is_x = 1'b1;
|
//index = alu_x;
|
//index = alu_x;
|
end
|
end
|
ADC_ABY, AND_ABY, CMP_ABY, EOR_ABY, LDA_ABY, LDX_ABY, ORA_ABY, SBC_ABY, STA_ABY: begin
|
ADC_ABY, AND_ABY, CMP_ABY, EOR_ABY, LDA_ABY, LDX_ABY, ORA_ABY, SBC_ABY, STA_ABY: begin
|
absolute_indexed = 1'b1;
|
absolute_indexed = 1'b1;
|
index_is_x = 1'b0;
|
index_is_x = 1'b0;
|
//index = alu_y;
|
//index = alu_y;
|
end
|
end
|
ADC_IDX, AND_IDX, CMP_IDX, EOR_IDX, LDA_IDX, ORA_IDX, SBC_IDX, STA_IDX: begin
|
ADC_IDX, AND_IDX, CMP_IDX, EOR_IDX, LDA_IDX, ORA_IDX, SBC_IDX, STA_IDX: begin
|
indirectx = 1'b1;
|
indirectx = 1'b1;
|
index_is_x = 1'b1;
|
index_is_x = 1'b1;
|
//index = alu_x;
|
//index = alu_x;
|
end
|
end
|
ADC_IDY, AND_IDY, CMP_IDY, EOR_IDY, LDA_IDY, ORA_IDY, SBC_IDY, STA_IDY: begin
|
ADC_IDY, AND_IDY, CMP_IDY, EOR_IDY, LDA_IDY, ORA_IDY, SBC_IDY, STA_IDY: begin
|
indirecty = 1'b1;
|
indirecty = 1'b1;
|
index_is_x = 1'b0;
|
index_is_x = 1'b0;
|
//index = alu_y;
|
//index = alu_y;
|
end
|
end
|
JMP_ABS: begin
|
JMP_ABS: begin
|
absolute = 1'b1;
|
absolute = 1'b1;
|
jump = 1'b1;
|
jump = 1'b1;
|
end
|
end
|
JMP_IND: begin
|
JMP_IND: begin
|
jump_indirect = 1'b1;
|
jump_indirect = 1'b1;
|
end
|
end
|
BRK_IMP: begin
|
BRK_IMP: begin
|
brk = 1'b1;
|
brk = 1'b1;
|
end
|
end
|
RTI_IMP: begin
|
RTI_IMP: begin
|
rti = 1'b1;
|
rti = 1'b1;
|
end
|
end
|
RTS_IMP: begin
|
RTS_IMP: begin
|
rts = 1'b1;
|
rts = 1'b1;
|
end
|
end
|
PHA_IMP: begin
|
PHA_IMP: begin
|
pha = 1'b1;
|
pha = 1'b1;
|
end
|
end
|
PHP_IMP: begin
|
PHP_IMP: begin
|
php = 1'b1;
|
php = 1'b1;
|
end
|
end
|
PLA_IMP: begin
|
PLA_IMP: begin
|
pla = 1'b1;
|
pla = 1'b1;
|
end
|
end
|
PLP_IMP: begin
|
PLP_IMP: begin
|
plp = 1'b1;
|
plp = 1'b1;
|
end
|
end
|
JSR_ABS: begin
|
JSR_ABS: begin
|
jsr = 1'b1;
|
jsr = 1'b1;
|
end
|
end
|
TSX_IMP: begin
|
TSX_IMP: begin
|
tsx = 1'b1;
|
tsx = 1'b1;
|
end
|
end
|
TXS_IMP: begin
|
TXS_IMP: begin
|
txs = 1'b1;
|
txs = 1'b1;
|
end
|
end
|
default: begin
|
default: begin
|
index_is_x = 1'b1;
|
index_is_x = 1'b1;
|
//$write("state : %b", state);
|
//$write("state : %b", state);
|
if (reset_n == 1'b1 && state != FETCH_OP_FIX_PC) begin // the processor is NOT being reset neither it is fixing the pc
|
if (reset_n == 1'b1 && state != FETCH_OP_FIX_PC) begin // the processor is NOT being reset neither it is fixing the pc
|
//$write("\nunknown OPCODE!!!!! 0x%h\n", ir);
|
//$write("\nunknown OPCODE!!!!! 0x%h\n", ir);
|
//$finish();
|
//$finish();
|
end
|
end
|
end
|
end
|
endcase
|
endcase
|
|
|
case (ir)
|
case (ir)
|
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,
|
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,
|
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
|
DEC_ABX: begin
|
read_modify_write = 1'b1;
|
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
|
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;
|
write = 1'b1;
|
end
|
end
|
default: begin // this should work fine since the previous case statement will detect the unknown/undocumented/unsupported opcodes
|
default: begin // this should work fine since the previous case statement will detect the unknown/undocumented/unsupported opcodes
|
read = 1'b1;
|
read = 1'b1;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
endmodule
|
endmodule
|
|
|
|
|
|
|
|
|