Line 46... |
Line 46... |
//// ////
|
//// ////
|
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
|
|
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
|
|
module t6507lp_fsm(clk, reset_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, alu_x, alu_y);
|
parameter DATA_SIZE = 4'h8;
|
parameter DATA_SIZE = 4'h8;
|
parameter ADDR_SIZE = 4'hd;
|
parameter ADDR_SIZE = 4'hd;
|
|
|
localparam DATA_SIZE_ = DATA_SIZE - 4'b0001;
|
localparam DATA_SIZE_ = DATA_SIZE - 4'b0001;
|
localparam ADDR_SIZE_ = ADDR_SIZE - 4'b0001;
|
localparam ADDR_SIZE_ = ADDR_SIZE - 4'b0001;
|
Line 65... |
Line 65... |
output reg [DATA_SIZE_:0] data_out;
|
output reg [DATA_SIZE_:0] data_out;
|
output reg [DATA_SIZE_:0] alu_opcode;
|
output reg [DATA_SIZE_:0] alu_opcode;
|
output reg [DATA_SIZE_:0] alu_a;
|
output reg [DATA_SIZE_:0] alu_a;
|
output reg alu_enable;
|
output reg alu_enable;
|
|
|
|
input [DATA_SIZE_:0] alu_x;
|
|
input [DATA_SIZE_:0] alu_y;
|
|
|
|
|
// FSM states
|
// FSM states
|
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;
|
Line 76... |
Line 79... |
localparam FETCH_HIGH = 4'b0011;
|
localparam FETCH_HIGH = 4'b0011;
|
localparam READ_MEM = 4'b0100;
|
localparam READ_MEM = 4'b0100;
|
localparam DUMMY_WRT_CALC = 4'b0101;
|
localparam DUMMY_WRT_CALC = 4'b0101;
|
localparam WRITE_MEM = 4'b0110;
|
localparam WRITE_MEM = 4'b0110;
|
localparam FETCH_OP_CALC_PARAM = 4'b0111;
|
localparam FETCH_OP_CALC_PARAM = 4'b0111;
|
|
localparam READ_MEM_CALC_INDEX = 4'b1000;
|
|
|
// 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 103... |
Line 107... |
reg implied;
|
reg implied;
|
reg indirect;
|
reg indirect;
|
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
|
|
|
// 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;
|
|
|
wire [ADDR_SIZE_:0] next_pc;
|
wire [ADDR_SIZE_:0] next_pc;
|
assign next_pc = pc + 13'b0000000000001;
|
assign next_pc = pc + 13'b0000000000001;
|
|
|
|
wire [ADDR_SIZE_:0] address_plus_index; // this would update more times than actually needed, consuming power.
|
|
// so the assign was changed to conditional.
|
|
assign address_plus_index = (zero_page_indexed == 1'b1 && state == READ_MEM_CALC_INDEX)? (temp_addr + index): 0;
|
|
|
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 <= 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.
|
Line 180... |
Line 189... |
else begin
|
else begin
|
control <= MEM_READ;
|
control <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
end
|
end
|
|
else if (zero_page_indexed) begin
|
|
pc <= next_pc;
|
|
address <= {{5{1'b0}},data_in};
|
|
temp_addr <= {{5{1'b0}},data_in};
|
|
control <= MEM_READ;
|
|
end
|
end
|
end
|
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]};
|
Line 225... |
Line 240... |
temp_data <= data_in;
|
temp_data <= data_in;
|
control <= MEM_READ;
|
control <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
end
|
end
|
|
READ_MEM_CALC_INDEX: begin
|
|
//pc <= next_pc; // pc was already updated in the previous cycle
|
|
address <= address_plus_index;
|
|
temp_addr <= address_plus_index;
|
|
|
|
if (write) begin
|
|
control <= MEM_WRITE;
|
|
data_out <= alu_result;
|
|
end
|
|
else begin
|
|
control <= MEM_READ;
|
|
data_out <= 8'h00;
|
|
end
|
|
|
|
end
|
DUMMY_WRT_CALC: begin
|
DUMMY_WRT_CALC: begin
|
pc <= pc;
|
pc <= pc;
|
address <= temp_addr;
|
address <= temp_addr;
|
control <= MEM_WRITE;
|
control <= MEM_WRITE;
|
data_out <= alu_result;
|
data_out <= alu_result;
|
Line 286... |
Line 316... |
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_enable = 1'b1;
|
|
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
|
|
next_state = READ_MEM_CALC_INDEX;
|
|
end
|
else begin // at least the absolute address mode falls here
|
else begin // at least the absolute address mode falls here
|
next_state = FETCH_HIGH;
|
next_state = FETCH_HIGH;
|
end
|
if (write) begin // this is being done one cycle early?
|
|
|
if (write) begin
|
|
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
|
end
|
FETCH_HIGH: begin
|
FETCH_HIGH: begin
|
if (jump) begin
|
if (jump) begin
|
next_state = FETCH_OP;
|
next_state = FETCH_OP;
|
end
|
end
|
Line 319... |
Line 352... |
else begin
|
else begin
|
$write("unknown behavior");
|
$write("unknown behavior");
|
$finish(0);
|
$finish(0);
|
end
|
end
|
end
|
end
|
|
READ_MEM_CALC_INDEX: 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
|
|
else begin
|
|
$write("unknown behavior");
|
|
$finish(0);
|
|
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
|
Line 354... |
Line 401... |
indirect = 1'b0;
|
indirect = 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;
|
|
|
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;
|
|
|
Line 375... |
Line 424... |
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, LDX_ZPY, STX_ZPY, STY_ZPX: begin
|
SBC_ZPX, STA_ZPX, STY_ZPX: begin
|
|
zero_page_indexed = 1'b1;
|
|
index = alu_x;
|
|
end
|
|
LDX_ZPY, STX_ZPY: begin
|
zero_page_indexed = 1'b1;
|
zero_page_indexed = 1'b1;
|
|
index = alu_y;
|
end
|
end
|
BCC_REL, BCS_REL, BEQ_REL, BMI_REL, BNE_REL, BPL_REL, BVC_REL, BVS_REL: begin
|
BCC_REL, BCS_REL, BEQ_REL, BMI_REL, BNE_REL, BPL_REL, BVC_REL, BVS_REL: begin
|
relative = 1'b1;
|
relative = 1'b1;
|
end
|
end
|
ADC_ABS, AND_ABS, ASL_ABS, BIT_ABS, CMP_ABS, CPX_ABS, CPY_ABS, DEC_ABS, EOR_ABS, INC_ABS, JMP_ABS, JSR_ABS, LDA_ABS,
|
ADC_ABS, AND_ABS, ASL_ABS, BIT_ABS, CMP_ABS, CPX_ABS, CPY_ABS, DEC_ABS, EOR_ABS, INC_ABS, JMP_ABS, JSR_ABS, LDA_ABS,
|
Line 394... |
Line 448... |
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
|
default: begin
|
|
if (reset_n == 1) begin // the processor is NOT being reset
|
$write("\nunknown OPCODE!!!!! 0x%h\n", ir);
|
$write("\nunknown OPCODE!!!!! 0x%h\n", ir);
|
$finish();
|
$finish();
|
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,
|
Line 416... |
Line 472... |
endcase
|
endcase
|
|
|
if (ir == JMP_ABS || ir == JMP_IND) begin // the opcodes are 8'h4C and 8'h6C
|
if (ir == JMP_ABS || ir == JMP_IND) begin // the opcodes are 8'h4C and 8'h6C
|
jump = 1'b1;
|
jump = 1'b1;
|
end
|
end
|
end // no way
|
end
|
endmodule
|
endmodule
|
|
|
|
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|