Line 80... |
Line 80... |
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;
|
localparam READ_MEM_CALC_INDEX = 4'b1000;
|
localparam FETCH_HIGH_CALC_INDEX = 4'b1001;
|
localparam FETCH_HIGH_CALC_INDEX = 4'b1001;
|
localparam READ_MEM_FIX_ADDR = 4'b1010;
|
localparam READ_MEM_FIX_ADDR = 4'b1010;
|
|
localparam FETCH_OP_EVAL_BRANCH = 4'b1011;
|
|
localparam FETCH_OP_FIX_PC = 4'b1100;
|
localparam RESET = 4'b1111;
|
localparam RESET = 4'b1111;
|
|
|
// OPCODES TODO: verify how this get synthesised
|
// OPCODES TODO: verify how this get synthesised
|
`include "../T6507LP_Package.v"
|
`include "../T6507LP_Package.v"
|
|
|
Line 122... |
Line 124... |
assign next_pc = pc + 13'b0000000000001;
|
assign next_pc = pc + 13'b0000000000001;
|
|
|
reg [ADDR_SIZE_:0] address_plus_index; // this would update more times than actually needed, consuming power.
|
reg [ADDR_SIZE_:0] address_plus_index; // this would update more times than actually needed, consuming power.
|
reg page_crossed; // so the simple assign was changed into a combinational always block
|
reg page_crossed; // so the simple assign was changed into a combinational always block
|
|
|
|
reg branch;
|
|
|
always @(*) begin
|
always @(*) begin
|
address_plus_index = 0;
|
address_plus_index = 0;
|
page_crossed = 0;
|
page_crossed = 0;
|
|
|
if (state == READ_MEM_CALC_INDEX || state == READ_MEM_FIX_ADDR || state == FETCH_HIGH_CALC_INDEX) begin
|
if (state == READ_MEM_CALC_INDEX || state == READ_MEM_FIX_ADDR || state == 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
|
|
else if (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;
|
|
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
|
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
|
Line 174... |
Line 183... |
if (accumulator || implied) begin
|
if (accumulator || implied) begin
|
pc <= pc; // is this better?
|
pc <= pc; // is this better?
|
address <= pc;
|
address <= pc;
|
control <= MEM_READ;
|
control <= MEM_READ;
|
end
|
end
|
else if (immediate) begin
|
else if (immediate || relative) begin
|
pc <= next_pc;
|
pc <= next_pc;
|
address <= next_pc;
|
address <= next_pc;
|
control <= MEM_READ;
|
control <= 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
|
Line 214... |
Line 223... |
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]};
|
control <= MEM_READ;
|
control <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
|
FETCH_OP_EVAL_BRANCH: begin
|
|
if (branch) begin
|
|
pc <= {{5{1'b0}}, address_plus_index[7:0]};
|
|
address <= {{5{1'b0}}, address_plus_index[7:0]};
|
|
control <= MEM_READ;
|
|
data_out <= 8'h00;
|
|
end
|
|
else begin
|
|
pc <= next_pc;
|
|
address <= next_pc;
|
|
control <= MEM_READ;
|
|
data_out <= 8'h00;
|
|
end
|
|
end
|
|
FETCH_OP_FIX_PC: begin
|
|
if (page_crossed) begin
|
|
pc[12:8] <= address_plus_index[12:8];
|
|
address[12:8] <= address_plus_index[12:8];
|
|
end
|
|
else begin
|
|
pc <= next_pc;
|
|
address <= next_pc;
|
|
control <= MEM_READ;
|
|
ir <= data_in;
|
|
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]};
|
control <= MEM_READ;
|
control <= MEM_READ;
|
Line 385... |
Line 420... |
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
|
|
next_state = FETCH_OP_EVAL_BRANCH;
|
|
end
|
|
end
|
|
FETCH_OP_EVAL_BRANCH: begin
|
|
if (branch) begin
|
|
next_state = FETCH_OP_FIX_PC;
|
|
end
|
|
else begin
|
|
next_state = FETCH_LOW;
|
|
end
|
|
end
|
|
FETCH_OP_FIX_PC: begin
|
|
if (page_crossed) begin
|
|
next_state = FETCH_OP;
|
|
end
|
|
else begin
|
|
next_state = FETCH_LOW;
|
|
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
|
Line 479... |
Line 533... |
|
|
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;
|
|
branch = 1'b0;
|
|
|
|
//$write("trying with %h\n", ir);
|
|
|
case (ir)
|
case (ir)
|
BRK_IMP, CLC_IMP, CLD_IMP, CLI_IMP, CLV_IMP, DEX_IMP, DEY_IMP, INX_IMP, INY_IMP, NOP_IMP, PHA_IMP, PHP_IMP, PLA_IMP,
|
BRK_IMP, CLC_IMP, CLD_IMP, CLI_IMP, CLV_IMP, DEX_IMP, DEY_IMP, INX_IMP, INY_IMP, NOP_IMP, PHA_IMP, PHP_IMP, PLA_IMP,
|
PLP_IMP, RTI_IMP, RTS_IMP, SEC_IMP, SED_IMP, SEI_IMP, TAX_IMP, TAY_IMP, TSX_IMP, TXA_IMP, TXS_IMP, TYA_IMP: begin
|
PLP_IMP, RTI_IMP, RTS_IMP, SEC_IMP, SED_IMP, SEI_IMP, TAX_IMP, TAY_IMP, TSX_IMP, TXA_IMP, TXS_IMP, TYA_IMP: begin
|
implied = 1'b1;
|
implied = 1'b1;
|
Line 504... |
Line 561... |
end
|
end
|
LDX_ZPY, STX_ZPY: begin
|
LDX_ZPY, STX_ZPY: begin
|
zero_page_indexed = 1'b1;
|
zero_page_indexed = 1'b1;
|
index = alu_y;
|
index = alu_y;
|
end
|
end
|
BCC_REL, BCS_REL, BEQ_REL, BMI_REL, BNE_REL, BPL_REL, BVC_REL, BVS_REL: begin
|
BCC_REL: begin
|
relative = 1'b1;
|
relative = 1'b1;
|
|
index = temp_data;
|
|
|
|
if (!alu_status[C]) begin
|
|
branch = 1'b1;
|
|
end
|
|
else begin
|
|
branch = 1'b0;
|
|
end
|
|
end
|
|
BCS_REL: begin
|
|
relative = 1'b1;
|
|
index = temp_data;
|
|
|
|
if (alu_status[C]) begin
|
|
branch = 1'b1;
|
|
end
|
|
else begin
|
|
branch = 1'b0;
|
|
end
|
|
end
|
|
BEQ_REL: begin
|
|
relative = 1'b1;
|
|
index = temp_data;
|
|
|
|
if (alu_status[Z]) begin
|
|
branch = 1'b1;
|
|
end
|
|
else begin
|
|
branch = 1'b0;
|
|
end
|
|
end
|
|
BNE_REL: begin
|
|
relative = 1'b1;
|
|
index = temp_data;
|
|
|
|
if (alu_status[Z] == 1'b0) begin
|
|
branch = 1'b1;
|
|
end
|
|
else begin
|
|
branch = 1'b0;
|
|
end
|
|
end
|
|
BPL_REL: begin
|
|
relative = 1'b1;
|
|
index = temp_data;
|
|
|
|
if (!alu_status[N]) begin
|
|
branch = 1'b1;
|
|
end
|
|
else begin
|
|
branch = 1'b0;
|
|
end
|
|
end
|
|
BMI_REL: begin
|
|
relative = 1'b1;
|
|
index = temp_data;
|
|
|
|
if (alu_status[N]) begin
|
|
branch = 1'b1;
|
|
end
|
|
else begin
|
|
branch = 1'b0;
|
|
end
|
|
end
|
|
BVC_REL: begin
|
|
relative = 1'b1;
|
|
index = temp_data;
|
|
|
|
if (!alu_status[V]) begin
|
|
branch = 1'b1;
|
|
end
|
|
else begin
|
|
branch = 1'b0;
|
|
end
|
|
end
|
|
BVS_REL: begin
|
|
relative = 1'b1;
|
|
index = temp_data;
|
|
|
|
if (alu_status[V]) begin
|
|
branch = 1'b1;
|
|
end
|
|
else begin
|
|
branch = 1'b0;
|
|
end
|
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,
|
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
|
Line 525... |
Line 667... |
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("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
|
$write("\nunknown OPCODE!!!!! 0x%h\n", ir);
|
$write("\nunknown OPCODE!!!!! 0x%h\n", ir);
|
$finish();
|
$finish();
|
end
|
end
|
end
|
end
|
endcase
|
endcase
|