Line 8... |
Line 8... |
//// 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 ////
|
//// - 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 ////
|
Line 142... |
Line 143... |
reg php;
|
reg php;
|
reg pla;
|
reg pla;
|
reg plp;
|
reg plp;
|
reg jsr;
|
reg jsr;
|
|
|
wire [ADDR_SIZE_:0] next_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;
|
|
|
reg [ADDR_SIZE_:0] address_plus_index; // this would update more times than actually needed, consuming power.
|
wire [8:0] sp_plus_one; // simple adder and subtracter for the stack pointer
|
reg page_crossed; // so the simple assign was changed into a combinational always block
|
assign sp_plus_one = sp + 9'b000000001;
|
|
|
|
wire [8:0] sp_minus_one;
|
|
assign sp_minus_one = sp - 9'b000000001;
|
|
|
|
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 branch;
|
reg branch; // a simple reg that is asserted everytime a branch will be executed.
|
|
|
|
// this is the combinational logic related to indexed instructions
|
always @(*) begin
|
always @(*) begin
|
address_plus_index = 8'h00;
|
address_plus_index = 8'h00;
|
page_crossed = 1'b0;
|
page_crossed = 1'b0;
|
|
|
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
|
Line 188... |
Line 196... |
{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
|
end
|
end
|
|
|
wire [8:0] sp_plus_one;
|
|
assign sp_plus_one = sp + 9'b000000001;
|
|
|
|
wire [8:0] sp_minus_one;
|
|
assign sp_minus_one = sp - 9'b000000001;
|
|
|
|
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 <= 9'b000000000; // the default is 'h100
|
sp <= 9'b000000000; // the default is 'h100
|
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 <= 0;
|
address <= 13'h0000;
|
mem_rw <= MEM_READ;
|
mem_rw <= MEM_READ;
|
data_out <= 8'h00;
|
data_out <= 8'h00;
|
end
|
end
|
else begin
|
else begin
|
state <= next_state;
|
state <= next_state;
|
Line 228... |
Line 230... |
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 instruction execute this cycle.
|
all instructions execute this cycle.
|
*/
|
*/
|
FETCH_LOW: begin
|
FETCH_LOW: begin
|
if (accumulator || implied) begin
|
if (accumulator || implied) begin
|
pc <= pc; // is this better?
|
pc <= pc; // is this better?
|
address <= pc;
|
address <= pc;
|
Line 366... |
Line 368... |
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_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;
|
Line 401... |
Line 404... |
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
|
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;
|
Line 424... |
Line 427... |
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.
|
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;
|
Line 566... |
Line 570... |
|
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
always @ (*) begin // this is the next_state logic and the 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
|
|
|