Line 7... |
Line 7... |
//// ////
|
//// ////
|
//// Description ////
|
//// Description ////
|
//// 6507 FSM ////
|
//// 6507 FSM ////
|
//// ////
|
//// ////
|
//// TODO: ////
|
//// TODO: ////
|
//// - Fix absolute indexed mode ////
|
|
//// - Code the relative mode ////
|
|
//// - Code the indexed indirect mode ////
|
//// - Code the indexed indirect mode ////
|
//// - Code the indirect indexed mode ////
|
//// - Code the indirect indexed mode ////
|
//// - Code the absolute indirect mode ////
|
//// - Code the absolute indirect mode ////
|
//// ////
|
//// ////
|
//// Author(s): ////
|
//// Author(s): ////
|
Line 69... |
Line 67... |
|
|
input [DATA_SIZE_:0] alu_x;
|
input [DATA_SIZE_:0] alu_x;
|
input [DATA_SIZE_:0] alu_y;
|
input [DATA_SIZE_:0] alu_y;
|
|
|
// FSM states
|
// FSM states
|
localparam FETCH_OP = 4'b0000;
|
localparam FETCH_OP = 5'b00000;
|
localparam FETCH_OP_CALC = 4'b0001;
|
localparam FETCH_OP_CALC = 5'b00001;
|
localparam FETCH_LOW = 4'b0010;
|
localparam FETCH_LOW = 5'b00010;
|
localparam FETCH_HIGH = 4'b0011;
|
localparam FETCH_HIGH = 5'b00011;
|
localparam READ_MEM = 4'b0100;
|
localparam READ_MEM = 5'b00100;
|
localparam DUMMY_WRT_CALC = 4'b0101;
|
localparam DUMMY_WRT_CALC = 5'b00101;
|
localparam WRITE_MEM = 4'b0110;
|
localparam WRITE_MEM = 5'b00110;
|
localparam FETCH_OP_CALC_PARAM = 4'b0111;
|
localparam FETCH_OP_CALC_PARAM = 5'b00111;
|
localparam READ_MEM_CALC_INDEX = 4'b1000;
|
localparam READ_MEM_CALC_INDEX = 5'b01000;
|
localparam FETCH_HIGH_CALC_INDEX = 4'b1001;
|
localparam FETCH_HIGH_CALC_INDEX = 5'b01001;
|
localparam READ_MEM_FIX_ADDR = 4'b1010;
|
localparam READ_MEM_FIX_ADDR = 5'b01010;
|
localparam FETCH_OP_EVAL_BRANCH = 4'b1011;
|
localparam FETCH_OP_EVAL_BRANCH = 5'b01011;
|
localparam FETCH_OP_FIX_PC = 4'b1100;
|
localparam FETCH_OP_FIX_PC = 5'b01100;
|
localparam RESET = 4'b1111;
|
localparam READ_FROM_POINTER = 5'b01101;
|
|
localparam READ_FROM_POINTER_X = 5'b01110;
|
|
localparam READ_FROM_POINTER_X1 = 5'b01111;
|
|
|
|
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"
|
|
|
// control signals
|
// control signals
|
Line 106... |
Line 108... |
reg absolute;
|
reg absolute;
|
reg absolute_indexed;
|
reg absolute_indexed;
|
reg accumulator;
|
reg accumulator;
|
reg immediate;
|
reg immediate;
|
reg implied;
|
reg implied;
|
reg indirect;
|
reg indirectx;
|
|
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
|
|
|
Line 140... |
Line 143... |
if (state == FETCH_OP_FIX_PC || state == FETCH_OP_EVAL_BRANCH) begin
|
if (state == FETCH_OP_FIX_PC || state == FETCH_OP_EVAL_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;// warning: pc might feed these lines twice and cause branch failure
|
address_plus_index[12:8] = pc[12:8] + page_crossed;// 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
|
|
else if (state == READ_FROM_POINTER) begin
|
|
{page_crossed, address_plus_index[7:0]} = temp_data + index;
|
|
address_plus_index[12:8] = 5'b00000;
|
|
end
|
|
else if (state == READ_FROM_POINTER_X) begin
|
|
{page_crossed, address_plus_index[7:0]} = temp_data + index + 8'h01;
|
|
address_plus_index[12:8] = 5'b00000;
|
|
end
|
end
|
end
|
|
|
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
|
Line 215... |
Line 226... |
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};
|
control <= MEM_READ;
|
control <= MEM_READ;
|
end
|
end
|
|
else if (indirectx) begin
|
|
pc <= next_pc;
|
|
address <= data_in;
|
|
temp_data <= data_in;
|
|
control <= MEM_READ;
|
|
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]};
|
Line 235... |
Line 252... |
else begin
|
else begin
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= next_pc;
|
address <= next_pc;
|
control <= MEM_READ;
|
control <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
|
ir <= data_in;
|
end
|
end
|
end
|
end
|
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];
|
Line 348... |
Line 366... |
pc <= pc;
|
pc <= pc;
|
address <= pc;
|
address <= pc;
|
control <= MEM_READ;
|
control <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
|
READ_FROM_POINTER: begin
|
|
pc <= pc;
|
|
address <= address_plus_index;
|
|
//temp_addr[7:0] <= data_in;
|
|
control <= MEM_READ;
|
|
end
|
|
READ_FROM_POINTER_X: begin
|
|
pc <= pc;
|
|
address <= address_plus_index;
|
|
temp_addr[7:0] <= data_in;
|
|
control <= MEM_READ;
|
|
end
|
|
READ_FROM_POINTER_X1: begin
|
|
pc <= pc;
|
|
address <= {data_in[5:0], temp_addr[7:0]};
|
|
if (write) begin
|
|
control <= MEM_WRITE;
|
|
end
|
|
else begin
|
|
control <= MEM_READ;
|
|
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
|
|
|
Line 423... |
Line 463... |
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) begin
|
|
next_state = READ_FROM_POINTER;
|
|
end
|
|
end
|
|
READ_FROM_POINTER: begin
|
|
next_state = READ_FROM_POINTER_X;
|
|
end
|
|
READ_FROM_POINTER_X: begin
|
|
next_state = READ_FROM_POINTER_X1;
|
|
end
|
|
READ_FROM_POINTER_X1: begin
|
|
if (read || read_modify_write) begin
|
|
next_state = READ_MEM;
|
|
end
|
|
else if (write) begin
|
|
alu_opcode = ir;
|
|
alu_enable = 1'b1;
|
|
next_state = WRITE_MEM;
|
|
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
|
Line 522... |
Line 581... |
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;
|
indirect = 1'b0;
|
indirectx = 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 = 1'b0;
|
index = 1'b0;
|
Line 662... |
Line 722... |
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 = alu_y;
|
index = alu_y;
|
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: begin
|
ORA_IDY, SBC_IDY, STA_IDY: begin // all these opcodes are 8'hX1; TODO: optimize this
|
indirectx = 1'b1;
|
indirect = 1'b1;
|
index = alu_x;
|
|
end
|
|
ADC_IDY, AND_IDY, CMP_IDY, EOR_IDY, LDA_IDY, ORA_IDY, SBC_IDY, STA_IDY: begin
|
|
indirecty = 1'b1;
|
|
index = alu_y;
|
end
|
end
|
default: begin
|
default: begin
|
$write("state : %b", state);
|
$write("state : %b", state);
|
if (reset_n == 1 && state != FETCH_OP_FIX_PC) begin // the processor is NOT being reset neither it is fixing the pc
|
if (reset_n == 1 && 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);
|