Line 16... |
Line 16... |
output wire [5:0] cpu_state_o,
|
output wire [5:0] cpu_state_o,
|
output wire cpu_we_o,
|
output wire cpu_we_o,
|
output wire cpu_oe_o,
|
output wire cpu_oe_o,
|
output wire [15:0] cpu_addr_o,
|
output wire [15:0] cpu_addr_o,
|
input wire [7:0] cpu_data_i,
|
input wire [7:0] cpu_data_i,
|
output wire [7:0] cpu_data_o
|
output wire [7:0] cpu_data_o,
|
|
input wire debug_clk,
|
|
output wire debug_data_o // serial debug info, 64 bit shift register
|
|
|
);
|
);
|
|
|
wire k_reset;
|
wire k_reset;
|
|
|
reg [7:0] k_opcode, k_postbyte, k_ind_ea; /* all bytes of an instruction */
|
reg [7:0] k_opcode, k_postbyte, k_ind_ea; /* all bytes of an instruction */
|
Line 83... |
Line 86... |
|
|
assign k_nmi_req = k_reg_nmi[2] & k_reg_nmi[1];
|
assign k_nmi_req = k_reg_nmi[2] & k_reg_nmi[1];
|
assign k_firq_req = k_reg_firq[2] & k_reg_firq[1];
|
assign k_firq_req = k_reg_firq[2] & k_reg_firq[1];
|
assign k_irq_req = k_reg_irq[2] & k_reg_irq[1];
|
assign k_irq_req = k_reg_irq[2] & k_reg_irq[1];
|
|
|
|
/* Debug */
|
|
`ifdef SERIAL_DEBUG
|
|
reg [63:0] debug_r;
|
|
|
|
always @(posedge debug_clk)
|
|
begin
|
|
if (cpu_clk)
|
|
begin
|
|
debug_r[15:0] <= regs_o_pc;
|
|
debug_r[23:16] <= k_opcode;
|
|
debug_r[27:24] <= datamux_o_alu_in_left_path_addr;
|
|
debug_r[31:28] <= dec_o_right_path_addr;
|
|
debug_r[35:32] <= datamux_o_dest_reg_addr;
|
|
debug_r[39:36] <= { k_write_pc, 1'b0, k_mem_dest}; //regs_o_CCR[3:0];
|
|
debug_r[55:40] <= { k_memhi,k_memlo };//k_new_pc;
|
|
debug_r[63:56] <= cpu_data_i;
|
|
end
|
|
else
|
|
debug_r <= debug_r << 1; // shift out
|
|
end
|
|
|
|
assign debug_data_o = debug_r[63];
|
|
`else
|
|
assign debug_data_o = 1'b0;
|
|
`endif
|
alu alu(
|
alu alu(
|
.clk_in(cpu_clk),
|
.clk_in(cpu_clk),
|
.a_in(datamux_o_alu_in_left_path_data),
|
.a_in(datamux_o_alu_in_left_path_data),
|
.b_in(datamux_o_alu_in_right_path_data),
|
.b_in(datamux_o_alu_in_right_path_data),
|
.CCR(regs_o_CCR), /* flags */
|
.CCR(regs_o_CCR), /* flags */
|
Line 250... |
Line 278... |
end
|
end
|
/* PC as destination from jmp/bsr mux */
|
/* PC as destination from jmp/bsr mux */
|
always @(*)
|
always @(*)
|
begin
|
begin
|
k_new_pc = { k_memhi,k_memlo }; // used to fetch reset vector
|
k_new_pc = { k_memhi,k_memlo }; // used to fetch reset vector
|
|
if (k_mem_dest != `MEMDEST_PC)
|
|
begin
|
case (dec_o_p1_mode)
|
case (dec_o_p1_mode)
|
`REL16: k_new_pc = regs_o_pc + { k_memhi,k_memlo };
|
`REL16: k_new_pc = regs_o_pc + { k_memhi,k_memlo };
|
`REL8: k_new_pc = regs_o_pc + { {8{k_memlo[7]}}, k_memlo };
|
`REL8: k_new_pc = regs_o_pc + { {8{k_memlo[7]}}, k_memlo };
|
`EXTENDED: k_new_pc = { k_eahi,k_ealo };
|
`EXTENDED: k_new_pc = { k_eahi,k_ealo };
|
`DIRECT: k_new_pc = { regs_o_dp, k_ealo };
|
`DIRECT: k_new_pc = { regs_o_dp, k_ealo };
|
Line 262... |
Line 292... |
k_new_pc = { k_memhi,k_memlo };
|
k_new_pc = { k_memhi,k_memlo };
|
else
|
else
|
k_new_pc = regs_o_eamem_addr;
|
k_new_pc = regs_o_eamem_addr;
|
endcase
|
endcase
|
end
|
end
|
|
end
|
/* ALU right input mux */
|
/* ALU right input mux */
|
always @(*)
|
always @(*)
|
begin
|
begin
|
case (dec_o_right_path_addr)
|
case (dec_o_right_path_addr)
|
`RN_MEM8:
|
`RN_MEM8:
|
Line 335... |
Line 366... |
k_forced_mem_size <= 1;
|
k_forced_mem_size <= 1;
|
state <= `SEQ_MEM_READ_H;
|
state <= `SEQ_MEM_READ_H;
|
k_eahi <= 8'hff;
|
k_eahi <= 8'hff;
|
k_ealo <= 8'hfe;
|
k_ealo <= 8'hfe;
|
next_mem_state <= `SEQ_LOADPC;
|
next_mem_state <= `SEQ_LOADPC;
|
|
k_mem_dest <= `MEMDEST_PC;
|
end
|
end
|
`SEQ_NMI:
|
`SEQ_NMI:
|
begin
|
begin
|
k_forced_mem_size <= 1;
|
k_forced_mem_size <= 1;
|
k_reg_nmi <= 3'h0;
|
k_reg_nmi <= 3'h0;
|
Line 416... |
Line 448... |
end
|
end
|
`SEQ_LOADPC: /* loads the PC with the address taken from the reset vector */
|
`SEQ_LOADPC: /* loads the PC with the address taken from the reset vector */
|
begin
|
begin
|
$display("cpu_data_i %02x %t", cpu_data_i, $time);
|
$display("cpu_data_i %02x %t", cpu_data_i, $time);
|
state <= `SEQ_FETCH;
|
state <= `SEQ_FETCH;
|
|
k_mem_dest <= `MEMDEST_MH; // operand to memlo/memhi
|
end
|
end
|
`SEQ_FETCH: /* execution starts here */
|
`SEQ_FETCH: /* execution starts here */
|
begin
|
begin
|
if (k_nmi_req)
|
if (k_nmi_req)
|
state <= `SEQ_NMI;
|
state <= `SEQ_NMI;
|
Line 480... |
Line 513... |
k_inc_pc <= 1;
|
k_inc_pc <= 1;
|
state <= `SEQ_DECODE_P23;
|
state <= `SEQ_DECODE_P23;
|
end
|
end
|
`SEQ_DECODE:
|
`SEQ_DECODE:
|
begin
|
begin
|
/* here we have the first byte of the k_opcode and should be decided to which state we jump
|
/* here we have the first byte of the opcode and should be decided to which state we jump
|
* inherent means that no extra info is needed
|
* inherent means that no extra info is needed
|
* ALU opcodes need routing of registers to/from the ALU to the registers
|
* ALU opcodes need routing of registers to/from the ALU to the registers
|
*/
|
*/
|
case (dec_o_p1_mode)
|
case (dec_o_p1_mode)
|
`NONE: // unknown k_opcode or push/pull... refetch ?
|
`NONE: // unknown opcode or push/pull... refetch ?
|
begin
|
begin
|
casex (k_opcode)
|
casex (k_opcode)
|
8'h13: state <= `SEQ_SYNC;
|
8'h13: state <= `SEQ_SYNC;
|
8'h39: // RTS
|
8'h39: // RTS
|
begin
|
begin
|
Line 532... |
Line 565... |
default: state <= `SEQ_GRAL_ALU;
|
default: state <= `SEQ_GRAL_ALU;
|
endcase
|
endcase
|
end
|
end
|
`DIRECT:
|
`DIRECT:
|
begin
|
begin
|
state <= `SEQ_PC_READ_L;
|
state <= `SEQ_PC_READ_L; // loads address
|
|
if (dec_o_p1_optype == `OP_JSR) // jsr
|
|
begin
|
|
next_state <= `SEQ_JSR_PUSH;
|
|
end
|
|
else
|
|
begin
|
k_mem_dest <= `MEMDEST_MH; // operand to memlo/memhi
|
k_mem_dest <= `MEMDEST_MH; // operand to memlo/memhi
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
(dec_o_left_path_addr == `RN_MEM8))
|
(dec_o_left_path_addr == `RN_MEM8))
|
begin
|
begin
|
next_state <= `SEQ_MEM_READ_H;
|
next_state <= `SEQ_MEM_READ_H;
|
Line 544... |
Line 583... |
end
|
end
|
else
|
else
|
next_state <= `SEQ_GRAL_ALU; // no read
|
next_state <= `SEQ_GRAL_ALU; // no read
|
k_eahi <= regs_o_dp;
|
k_eahi <= regs_o_dp;
|
end
|
end
|
|
end
|
`INDEXED:
|
`INDEXED:
|
state <= `SEQ_IND_READ_EA;
|
state <= `SEQ_IND_READ_EA;
|
`EXTENDED:
|
`EXTENDED:
|
begin
|
begin
|
state <= `SEQ_PC_READ_H; // loads address
|
state <= `SEQ_PC_READ_H; // loads address
|
|
if (dec_o_p1_optype == `OP_JSR) // jsr
|
|
begin
|
|
next_state <= `SEQ_JSR_PUSH;
|
|
end
|
|
else
|
|
begin
|
k_mem_dest <= `MEMDEST_MH; // operand to memlo/memhi
|
k_mem_dest <= `MEMDEST_MH; // operand to memlo/memhi
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
(dec_o_left_path_addr == `RN_MEM8))
|
(dec_o_left_path_addr == `RN_MEM8))
|
begin
|
begin
|
next_state <= `SEQ_MEM_READ_H;
|
next_state <= `SEQ_MEM_READ_H;
|
next_mem_state <= `SEQ_GRAL_ALU; // read then alu
|
next_mem_state <= `SEQ_GRAL_ALU; // read then alu
|
end
|
end
|
else
|
else
|
next_state <= `SEQ_GRAL_ALU; // no read
|
next_state <= `SEQ_GRAL_ALU; // no read
|
end
|
end
|
|
end
|
`REL8:
|
`REL8:
|
begin
|
begin
|
state <= `SEQ_PC_READ_L; // loads address
|
state <= `SEQ_PC_READ_L; // loads address
|
if (dec_o_p1_optype == `OP_JSR) // bsr
|
if (dec_o_p1_optype == `OP_JSR) // bsr
|
next_state <= `SEQ_JSR_PUSH;
|
next_state <= `SEQ_JSR_PUSH;
|
Line 695... |
Line 742... |
end
|
end
|
else
|
else
|
if (k_irq_req & `FLAGI)
|
if (k_irq_req & `FLAGI)
|
begin
|
begin
|
k_reg_irq <= 3'h0;
|
k_reg_irq <= 3'h0;
|
k_ealo[3:0] <= 4'hf8;
|
k_ealo[3:0] <= 4'h8;
|
state <= `SEQ_MEM_READ_H; // load new PC
|
state <= `SEQ_MEM_READ_H; // load new PC
|
end
|
end
|
end
|
end
|
`SEQ_SYNC: /* sync works like this:
|
`SEQ_SYNC: /* sync works like this:
|
* waits for an interrupt request
|
* waits for an interrupt request
|
Line 776... |
Line 823... |
begin // load 2 bytes offset
|
begin // load 2 bytes offset
|
state <= `SEQ_PC_READ_H;
|
state <= `SEQ_PC_READ_H;
|
next_state <= `SEQ_IND_DECODE_OFS; // has some offset, load arg
|
next_state <= `SEQ_IND_DECODE_OFS; // has some offset, load arg
|
end
|
end
|
else
|
else
|
//if (dec_o_ea_ofs0)
|
if (dec_o_p1_optype == `OP_JSR) // jsr
|
|
begin
|
|
next_state <= `SEQ_JSR_PUSH;
|
|
end
|
|
else
|
begin // no extra load...
|
begin // no extra load...
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
(dec_o_left_path_addr == `RN_MEM8))
|
(dec_o_left_path_addr == `RN_MEM8))
|
begin
|
begin
|
k_mem_dest <= `MEMDEST_MH; // operand land in k_memhi/lo
|
k_mem_dest <= `MEMDEST_MH; // operand land in k_memhi/lo
|
Line 791... |
Line 842... |
state <= `SEQ_GRAL_ALU; // no load, then store
|
state <= `SEQ_GRAL_ALU; // no load, then store
|
end
|
end
|
end
|
end
|
`SEQ_IND_DECODE_OFS: // loads argument if needed
|
`SEQ_IND_DECODE_OFS: // loads argument if needed
|
begin
|
begin
|
|
if (dec_o_p1_optype == `OP_JSR) // jsr
|
|
begin
|
|
next_state <= `SEQ_JSR_PUSH;
|
|
end
|
|
else
|
|
begin
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
(dec_o_left_path_addr == `RN_MEM8))
|
(dec_o_left_path_addr == `RN_MEM8))
|
begin
|
begin
|
k_mem_dest <= `MEMDEST_MH; // operand land in k_memhi/lo
|
k_mem_dest <= `MEMDEST_MH; // operand land in k_memhi/lo
|
next_mem_state <= `SEQ_GRAL_ALU;
|
next_mem_state <= `SEQ_GRAL_ALU;
|
state <= `SEQ_MEM_READ_H;
|
state <= `SEQ_MEM_READ_H;
|
end
|
end
|
else
|
else
|
state <= `SEQ_GRAL_ALU; // no load, then store
|
state <= `SEQ_GRAL_ALU; // no load, then store
|
end
|
end
|
|
end
|
`SEQ_JMP_LOAD_PC:
|
`SEQ_JMP_LOAD_PC:
|
begin
|
begin
|
state <= `SEQ_FETCH;
|
state <= `SEQ_FETCH;
|
end
|
end
|
`SEQ_JSR_PUSH:
|
`SEQ_JSR_PUSH:
|
Line 990... |
Line 1048... |
state <= `SEQ_MEM_READ_L_2;
|
state <= `SEQ_MEM_READ_L_2;
|
end
|
end
|
`SEQ_MEM_READ_L_2:
|
`SEQ_MEM_READ_L_2:
|
begin
|
begin
|
case (k_mem_dest)
|
case (k_mem_dest)
|
`MEMDEST_PC: begin k_memlo <= cpu_data_i; k_write_pc <= 1; end
|
`MEMDEST_PC,
|
`MEMDEST_MH: k_memlo <= cpu_data_i;
|
`MEMDEST_MH: k_memlo <= cpu_data_i;
|
`MEMDEST_AH: k_ealo <= cpu_data_i;
|
`MEMDEST_AH: k_ealo <= cpu_data_i;
|
endcase
|
endcase
|
case (dec_o_p1_mode)
|
case (dec_o_p1_mode)
|
`NONE, `INHERENT: k_write_dest <= 1; // pull, rts, rti
|
`NONE, `INHERENT: k_write_dest <= 1; // pull, rts, rti
|
endcase
|
endcase
|
|
if (next_mem_state == `SEQ_LOADPC)
|
|
k_write_pc <= 1;
|
state <= next_mem_state;
|
state <= next_mem_state;
|
end
|
end
|
`SEQ_MEM_WRITE_H: // writes high byte
|
`SEQ_MEM_WRITE_H: // writes high byte
|
begin
|
begin
|
case (dec_o_p1_mode)
|
case (dec_o_p1_mode)
|
Line 1044... |
Line 1104... |
k_mem_dest = 0;
|
k_mem_dest = 0;
|
k_new_pc = 16'hffff;
|
k_new_pc = 16'hffff;
|
k_write_tfr = 0;
|
k_write_tfr = 0;
|
k_write_exg = 0;
|
k_write_exg = 0;
|
k_mul_cnt = 0;
|
k_mul_cnt = 0;
|
|
k_write_dest = 0;
|
end
|
end
|
endmodule
|
endmodule
|
No newline at end of file
|
No newline at end of file
|
|
|
No newline at end of file
|
No newline at end of file
|