Line 38... |
Line 38... |
reg k_write_tfr, k_write_exg;
|
reg k_write_tfr, k_write_exg;
|
reg k_cpu_oe, k_cpu_we, k_inc_pc;
|
reg k_cpu_oe, k_cpu_we, k_inc_pc;
|
reg k_indirect_loaded; // set when in indirect indexed and the address has been loaded
|
reg k_indirect_loaded; // set when in indirect indexed and the address has been loaded
|
reg [15:0] k_cpu_addr, k_new_pc;
|
reg [15:0] k_cpu_addr, k_new_pc;
|
reg k_write_pc, k_inc_su, k_dec_su, k_set_e, k_clear_e;
|
reg k_write_pc, k_inc_su, k_dec_su, k_set_e, k_clear_e;
|
reg [1:0] k_mem_dest;
|
|
reg k_mul_cnt; // multiplier couner
|
reg k_mul_cnt; // multiplier couner
|
reg k_write_dest; // set for 1 clock when a register has to be written, dec_o_dest_reg_addr has the register source
|
reg k_write_dest; // set for 1 clock when a register has to be written, dec_o_dest_reg_addr has the register source
|
reg k_write_post_incdec; // asserted when in the last write cycle or in write back for loads
|
reg k_write_post_incdec; // asserted when in the last write cycle or in write back for loads
|
reg k_forced_mem_size; // used to force the size of a memory read to be 16 bits, used for vector fetch
|
reg k_forced_mem_size; // used to force the size of a memory read to be 16 bits, used for vector fetch
|
/****
|
/****
|
Line 53... |
Line 52... |
wire dec_o_alu_size; /* size of the result of an alu opcode (destination to be written) */
|
wire dec_o_alu_size; /* size of the result of an alu opcode (destination to be written) */
|
wire op_SYNC, op_EXG, op_TFR, op_RTS, op_RTI, op_CWAI;
|
wire op_SYNC, op_EXG, op_TFR, op_RTS, op_RTI, op_CWAI;
|
wire op_MUL, op_SWI, op_PUSH, op_PULL, op_LEA, op_JMP, op_JSR;
|
wire op_MUL, op_SWI, op_PUSH, op_PULL, op_LEA, op_JMP, op_JSR;
|
|
|
/* ea decoder */
|
/* ea decoder */
|
wire dec_o_ea_ofs8, dec_o_ea_ofs16, dec_o_ea_wpost, dec_o_ea_ofs0, dec_o_ea_indirect;
|
wire dec_o_ea_ofs8, dec_o_ea_ofs16, dec_o_ea_wpost, dec_o_ea_ofs5, dec_o_ea_indirect;
|
|
wire [3:0] dec_o_eabase, dec_o_eaidx;
|
/* alu k_opcode decoder */
|
/* alu k_opcode decoder */
|
wire [4:0] dec_o_alu_opcode;
|
wire [4:0] dec_o_alu_opcode;
|
wire [1:0] dec_o_right_path_mod; /* Modifier for alu's right path input */
|
wire [1:0] dec_o_right_path_mod; /* Modifier for alu's right path input */
|
/* register decoder */
|
/* register decoder */
|
wire dec_o_wdest, dec_o_source_size, dec_o_write_flags;
|
wire dec_o_wdest, dec_o_source_size, dec_o_write_flags;
|
wire [3:0] dec_o_left_path_addr, dec_o_right_path_addr, dec_o_dest_reg_addr;
|
wire [3:0] dec_o_left_path_addr, dec_o_right_path_addr, dec_o_dest_reg_addr;
|
// latched versions, used for muxes, regs and alu
|
// latched versions, used for muxes, regs and alu
|
wire [3:0] dec_lo_left_path_addr, dec_lo_right_path_addr, dec_lo_dest_reg_addr;
|
wire [3:0] dec_lo_left_path_addr, dec_lo_right_path_addr, dec_lo_dest_reg_addr;
|
|
wire [1:0] dec_o_left_path_memtype, dec_o_right_path_memtype, dec_o_dest_memtype;
|
|
wire [1:0] dec_lo_left_path_memtype, dec_lo_right_path_memtype, dec_lo_dest_memtype;
|
|
wire dec_o_operand_read, dec_o_operand_write;
|
/* test condition */
|
/* test condition */
|
wire dec_o_cond_taken;
|
wire dec_o_cond_taken;
|
/* ALU outputs */
|
/* ALU outputs */
|
wire [15:0] alu_o_result;
|
wire [15:0] alu_o_result;
|
wire [7:0] alu_o_CCR;
|
wire [7:0] alu_o_CCR;
|
Line 78... |
Line 81... |
reg [3:0] datamux_o_dest_reg_addr, datamux_o_alu_in_left_path_addr;
|
reg [3:0] datamux_o_dest_reg_addr, datamux_o_alu_in_left_path_addr;
|
reg [15:0] datamux_o_alu_in_left_path_data, datamux_o_alu_in_right_path_data, datamux_o_dest;
|
reg [15:0] datamux_o_alu_in_left_path_data, datamux_o_alu_in_right_path_data, datamux_o_dest;
|
|
|
reg k_p2_valid, k_p3_valid; /* 1 when k_postbyte has been loaded for page 2 or page 3 */
|
reg k_p2_valid, k_p3_valid; /* 1 when k_postbyte has been loaded for page 2 or page 3 */
|
|
|
|
reg [2:0] k_mem_state; /* Memory mini-state machine */
|
|
|
/*
|
/*
|
* Interrupt sync registers
|
* Interrupt sync registers
|
*/
|
*/
|
|
|
reg [2:0] k_reg_nmi, k_reg_irq, k_reg_firq;
|
reg [2:0] k_reg_nmi, k_reg_irq, k_reg_firq;
|
Line 102... |
Line 107... |
debug_r[15:0] <= regs_o_pc;
|
debug_r[15:0] <= regs_o_pc;
|
debug_r[23:16] <= k_opcode;
|
debug_r[23:16] <= k_opcode;
|
debug_r[27:24] <= datamux_o_alu_in_left_path_addr;
|
debug_r[27:24] <= datamux_o_alu_in_left_path_addr;
|
debug_r[31:28] <= dec_o_right_path_addr;
|
debug_r[31:28] <= dec_o_right_path_addr;
|
debug_r[35:32] <= datamux_o_dest_reg_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[39:36] <= { 3'b0, k_write_pc }; //regs_o_CCR[3:0];
|
debug_r[55:40] <= { k_memhi,k_memlo };//k_new_pc;
|
debug_r[55:40] <= { k_memhi,k_memlo };//k_new_pc;
|
debug_r[63:56] <= cpu_data_i;
|
debug_r[63:56] <= cpu_data_i;
|
end
|
end
|
else
|
else
|
debug_r <= debug_r << 1; // shift out
|
debug_r <= debug_r << 1; // shift out
|
Line 157... |
Line 162... |
.eamem_addr_o(regs_o_eamem_addr),
|
.eamem_addr_o(regs_o_eamem_addr),
|
.reg_pc(regs_o_pc),
|
.reg_pc(regs_o_pc),
|
.reg_dp(regs_o_dp),
|
.reg_dp(regs_o_dp),
|
.reg_su(regs_o_su)
|
.reg_su(regs_o_su)
|
);
|
);
|
|
decoders decs(
|
decode_regs dec_regs(
|
.clk_in(cpu_clk),
|
.cpu_clk(cpu_clk),
|
|
.opcode(k_opcode),
|
.opcode(k_opcode),
|
.postbyte0(k_postbyte),
|
.postbyte0(k_postbyte),
|
.page2_valid(k_p2_valid),
|
.page2_valid(k_p2_valid),
|
.page3_valid(k_p3_valid),
|
.page3_valid(k_p3_valid),
|
|
|
.path_left_addr_o(dec_o_left_path_addr),
|
.path_left_addr_o(dec_o_left_path_addr),
|
.path_right_addr_o(dec_o_right_path_addr),
|
.path_right_addr_o(dec_o_right_path_addr),
|
.dest_reg_o(dec_o_dest_reg_addr),
|
.dest_reg_o(dec_o_dest_reg_addr),
|
.path_left_addr_lo(dec_lo_left_path_addr),
|
.path_left_addr_lo(dec_lo_left_path_addr),
|
.path_right_addr_lo(dec_lo_right_path_addr),
|
.path_right_addr_lo(dec_lo_right_path_addr),
|
.dest_reg_lo(dec_lo_dest_reg_addr),
|
.dest_reg_lo(dec_lo_dest_reg_addr),
|
.write_dest(dec_o_wdest),
|
.write_dest(dec_o_wdest),
|
.source_size(dec_o_source_size),
|
.source_size(dec_o_source_size),
|
.result_size(dec_o_alu_size)
|
.result_size(dec_o_alu_size),
|
);
|
.path_left_memtype_o(dec_o_left_path_memtype),
|
|
.path_right_memtype_o(dec_o_right_path_memtype),
|
decode_op dec_op(
|
.dest_memtype_o(dec_o_dest_memtype),
|
.opcode(k_opcode),
|
.path_left_memtype_lo(dec_lo_left_path_memtype),
|
.postbyte0(k_postbyte),
|
.path_right_memtype_lo(dec_lo_right_path_memtype),
|
.page2_valid(k_p2_valid),
|
.dest_memtype_lo(dec_lo_dest_memtype),
|
.page3_valid(k_p3_valid),
|
.operand_read_o(dec_o_operand_read),
|
|
.operand_write_o(dec_o_operand_write),
|
.mode(dec_o_p1_mode),
|
.mode(dec_o_p1_mode),
|
.op_SYNC(op_SYNC),
|
.op_SYNC(op_SYNC),
|
.op_EXG (op_EXG ),
|
.op_EXG (op_EXG ),
|
.op_TFR (op_TFR ),
|
.op_TFR (op_TFR ),
|
.op_RTS (op_RTS ),
|
.op_RTS (op_RTS ),
|
Line 194... |
Line 200... |
.op_PUSH(op_PUSH),
|
.op_PUSH(op_PUSH),
|
.op_PULL(op_PULL),
|
.op_PULL(op_PULL),
|
.op_LEA (op_LEA ),
|
.op_LEA (op_LEA ),
|
.op_JSR (op_JSR ),
|
.op_JSR (op_JSR ),
|
.op_JMP (op_JMP ),
|
.op_JMP (op_JMP ),
|
.use_s(dec_o_use_s)
|
.use_s(dec_o_use_s),
|
|
.alu_opcode(dec_o_alu_opcode),
|
|
.dest_flags_o(dec_o_write_flags)
|
);
|
);
|
|
|
decode_ea dec_ea(
|
decode_ea dec_ea(
|
.eapostbyte( k_ind_ea ),
|
.eapostbyte( k_ind_ea ),
|
.noofs(dec_o_ea_ofs0),
|
.eabase_o(dec_o_eabase), // base register
|
.ofs8(dec_o_ea_ofs8),
|
.eaindex_o(dec_o_eaidx), // index register
|
.ofs16(dec_o_ea_ofs16),
|
.ea_ofs5_o(dec_o_ea_ofs5),
|
.write_post(dec_o_ea_wpost),
|
.ea_ofs8_o(dec_o_ea_ofs8),
|
.isind(dec_o_ea_indirect)
|
.ea_ofs16_o(dec_o_ea_ofs16),
|
|
.ea_is_indirect_o(dec_o_ea_indirect),
|
|
.ea_write_back_o(dec_o_ea_wpost)
|
);
|
);
|
|
|
/* Opcodes for the ALU are decoded here
|
|
* Write Flags are also decoded here
|
|
*/
|
|
decode_alu dec_alu(
|
|
.opcode(k_opcode),
|
|
.postbyte0(k_postbyte),
|
|
.page2_valid(k_p2_valid),
|
|
.page3_valid(k_p3_valid),
|
|
.alu_opcode(dec_o_alu_opcode),
|
|
.dec_alu_right_path_mod(dec_o_right_path_mod),
|
|
.dest_flags(dec_o_write_flags)
|
|
);
|
|
/* Condition decoder */
|
/* Condition decoder */
|
test_condition test_cond(
|
test_condition test_cond(
|
.opcode(k_opcode),
|
.opcode(k_opcode),
|
.postbyte0(k_postbyte),
|
.postbyte0(k_postbyte),
|
.page2_valid(k_p2_valid),
|
.page2_valid(k_p2_valid),
|
Line 236... |
Line 235... |
assign cpu_addr_o = k_cpu_addr;
|
assign cpu_addr_o = k_cpu_addr;
|
assign cpu_data_o = k_cpu_data_o;
|
assign cpu_data_o = k_cpu_data_o;
|
assign k_reset = cpu_reset;
|
assign k_reset = cpu_reset;
|
assign cpu_state_o = state;
|
assign cpu_state_o = state;
|
|
|
|
wire cpu_dtack_i = 1;
|
/* Left Register read mux
|
/* Left Register read mux
|
*/
|
*/
|
always @(*)
|
always @(*)
|
begin
|
begin
|
if (k_pp_active_reg != `RN_INV)
|
if (k_pp_active_reg != `RN_INV)
|
Line 281... |
Line 280... |
|
|
/* ALU left input mux */
|
/* ALU left input mux */
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
if (dec_lo_left_path_addr == `RN_MEM8)
|
if (dec_lo_left_path_memtype == `MT_BYTE)
|
datamux_o_alu_in_left_path_data = { k_memhi, k_memlo };
|
datamux_o_alu_in_left_path_data = { k_memhi, k_memlo };
|
else
|
else
|
if (op_LEA)
|
if (op_LEA)
|
begin
|
begin
|
if (dec_o_ea_indirect)// & dec_o_alu_size)
|
if (dec_o_ea_indirect)// & dec_o_alu_size)
|
Line 298... |
Line 297... |
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 };
|
`INDEXED:
|
`INDEXED:
|
if (dec_o_ea_indirect)
|
if (dec_o_ea_indirect)
|
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;
|
|
default:
|
|
k_new_pc = { k_memhi,k_memlo }; // used to fetch reset vector
|
endcase
|
endcase
|
end
|
end
|
end
|
|
/* ALU right input mux */
|
/* ALU right input mux */
|
always @(*)
|
always @(*)
|
begin
|
begin
|
case (dec_lo_right_path_addr)
|
|
`RN_MEM8:
|
|
datamux_o_alu_in_right_path_data = { 8'h00, k_memlo };
|
|
`RN_MEM16:
|
|
datamux_o_alu_in_right_path_data = { k_memhi, k_memlo };
|
datamux_o_alu_in_right_path_data = { k_memhi, k_memlo };
|
`RN_IMM8:
|
if ((dec_lo_right_path_memtype == `MT_NONE) &&
|
datamux_o_alu_in_right_path_data = { 8'h0, k_memlo };
|
(dec_o_p1_mode != `IMMEDIATE))
|
`RN_IMM16:
|
// datamux_o_alu_in_right_path_data = { k_memhi, k_memlo };
|
datamux_o_alu_in_right_path_data = { k_memhi, k_memlo };
|
//else
|
default:
|
datamux_o_alu_in_right_path_data = regs_o_right_path_data;
|
case (dec_o_right_path_mod)
|
// `MT_BYTE, `MT_WORD:
|
`MOD_DEFAULT: datamux_o_alu_in_right_path_data = regs_o_right_path_data;
|
// datamux_o_alu_in_right_path_data = { k_memhi, k_memlo };
|
`MOD_ONE: datamux_o_alu_in_right_path_data = 16'h0001;
|
// endcase
|
`MOD_ZERO: datamux_o_alu_in_right_path_data = 16'h0000;
|
|
`MOD_MINUS1: datamux_o_alu_in_right_path_data = 16'hffff;
|
|
endcase
|
|
endcase
|
|
end
|
end
|
|
|
always @(posedge cpu_clk or posedge k_reset)
|
always @(posedge cpu_clk or posedge k_reset)
|
begin
|
begin
|
if (k_reset == 1'b1)
|
if (k_reset == 1'b1)
|
Line 386... |
Line 376... |
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;
|
k_opcode <= 8'h15; // force the decoder for NONE, used in memory access
|
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 468... |
Line 458... |
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
|
|
case (k_mem_state)
|
|
3'h0: // start, output address
|
|
begin
|
|
k_p2_valid <= 0; // set when an k_opcode is page 2
|
|
k_p3_valid <= 0; // set when an k_opcode is page 3
|
|
k_pp_active_reg <= `RN_INV; // ensures that only push/pull control the left/dest muxes
|
if (k_nmi_req)
|
if (k_nmi_req)
|
state <= `SEQ_NMI;
|
state <= `SEQ_NMI;
|
else
|
else
|
if (k_firq_req & `FLAGF)
|
if (k_firq_req & `FLAGF)
|
state <= `SEQ_FIRQ;
|
state <= `SEQ_FIRQ;
|
else
|
else
|
if (k_irq_req & `FLAGI)
|
if (k_irq_req & `FLAGI)
|
state <= `SEQ_IRQ;
|
state <= `SEQ_IRQ;
|
else
|
else
|
begin
|
begin
|
state <= `SEQ_FETCH_1;
|
k_mem_state <= k_mem_state + 3'h1;
|
k_cpu_addr <= regs_o_pc;
|
k_cpu_addr <= regs_o_pc;
|
|
k_inc_pc <= 1;
|
end
|
end
|
end
|
end
|
`SEQ_FETCH_1:
|
3'h1:
|
begin
|
begin
|
k_cpu_oe <= 1;
|
k_cpu_oe <= 1;
|
k_inc_pc <= 1;
|
k_mem_state <= k_mem_state + 3'h1;
|
k_p2_valid <= 0; // set when an k_opcode is page 2
|
|
k_p3_valid <= 0; // set when an k_opcode is page 3
|
|
k_pp_active_reg <= `RN_INV; // ensures that only push/pull control the left/dest muxes
|
|
state <= `SEQ_FETCH_2;
|
|
end
|
end
|
`SEQ_FETCH_2:
|
3'h2:
|
|
if (cpu_dtack_i)
|
begin
|
begin
|
k_opcode <= cpu_data_i;
|
k_opcode <= cpu_data_i;
|
|
k_cpu_oe <= 0;
|
case (cpu_data_i[7:0]) /* page 2 & 3 opcodes are recognized here */
|
case (cpu_data_i[7:0]) /* page 2 & 3 opcodes are recognized here */
|
8'h10:
|
8'h10:
|
begin
|
begin
|
k_p2_valid <= 1;
|
k_p2_valid <= 1;
|
state <= `SEQ_FETCH_3;
|
k_mem_state <= k_mem_state + 3'h1;
|
end
|
end
|
8'h11:
|
8'h11:
|
begin
|
begin
|
k_p3_valid <= 1;
|
k_p3_valid <= 1;
|
state <= `SEQ_FETCH_3;
|
k_mem_state <= k_mem_state + 3'h1;
|
end
|
end
|
8'h1e, 8'h1f:
|
8'h1e, 8'h1f:
|
state <= `SEQ_FETCH_3; // tfr, exg, treated separately
|
k_mem_state <= k_mem_state + 3'h1; // tfr, exg, treated separately
|
default:
|
default:
|
|
begin
|
state <= `SEQ_DECODE;
|
state <= `SEQ_DECODE;
|
|
k_mem_state <= 3'h0;
|
|
end
|
endcase
|
endcase
|
end
|
end
|
`SEQ_FETCH_3:
|
3'h3:
|
begin
|
begin
|
state <= `SEQ_FETCH_4;
|
|
k_cpu_addr <= regs_o_pc;
|
k_cpu_addr <= regs_o_pc;
|
|
k_inc_pc <= 1;
|
|
k_mem_state <= k_mem_state + 3'h1;
|
end
|
end
|
`SEQ_FETCH_4:
|
3'h4:
|
begin
|
begin
|
k_cpu_oe <= 1;
|
k_cpu_oe <= 1;
|
state <= `SEQ_FETCH_5;
|
k_mem_state <= k_mem_state + 3'h1;
|
end
|
end
|
`SEQ_FETCH_5: /* fetches a page 2 or 3 opcode */
|
3'h5:
|
|
if (cpu_dtack_i)
|
begin
|
begin
|
|
k_mem_state <= 3'h0;
|
k_postbyte <= cpu_data_i;
|
k_postbyte <= cpu_data_i;
|
k_inc_pc <= 1;
|
k_cpu_oe <= 0;
|
state <= `SEQ_DECODE_P23;
|
state <= `SEQ_DECODE;
|
|
end
|
|
endcase
|
end
|
end
|
`SEQ_DECODE:
|
`SEQ_DECODE:
|
begin
|
begin
|
/* here we have the first byte of the 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
|
Line 552... |
Line 554... |
else if (op_PULL) // PULL S&U
|
else if (op_PULL) // PULL S&U
|
begin
|
begin
|
next_state <= `SEQ_PREPULL;
|
next_state <= `SEQ_PREPULL;
|
state <= `SEQ_PC_READ_L;
|
state <= `SEQ_PC_READ_L;
|
end
|
end
|
|
else if (op_EXG) begin k_write_exg <= 1; state <= `SEQ_TFREXG; end
|
|
else if (op_TFR) begin k_write_tfr <= 1; state <= `SEQ_TFREXG; end
|
else /* we ignore unknown opcodes */
|
else /* we ignore unknown opcodes */
|
state <= `SEQ_FETCH;
|
state <= `SEQ_FETCH;
|
end
|
end
|
`IMMEDIATE: // 8 or 16 bits as result decides..
|
`IMMEDIATE: // 8 or 16 bits as result decides..
|
begin
|
begin
|
Line 578... |
Line 582... |
k_pp_regs <= 8'h80; // Pull PC (RTS)all regs
|
k_pp_regs <= 8'h80; // Pull PC (RTS)all regs
|
end
|
end
|
else if (op_MUL)
|
else if (op_MUL)
|
begin k_mul_cnt <= 1'h1; state <= `SEQ_GRAL_ALU; end // counter for mul
|
begin k_mul_cnt <= 1'h1; state <= `SEQ_GRAL_ALU; end // counter for mul
|
else if (op_SWI)
|
else if (op_SWI)
|
|
begin
|
|
if (k_p2_valid) state <= `SEQ_SWI2;
|
|
else if (k_p3_valid) state <= `SEQ_SWI3;
|
|
else
|
state <= `SEQ_SWI;
|
state <= `SEQ_SWI;
|
|
end
|
else
|
else
|
state <= `SEQ_GRAL_ALU;
|
state <= `SEQ_GRAL_ALU;
|
end
|
end
|
`DIRECT:
|
`DIRECT:
|
begin
|
begin
|
state <= `SEQ_PC_READ_L; // loads address
|
state <= `SEQ_PC_READ_L; // loads address
|
if (op_JSR) next_state <= `SEQ_JSR_PUSH;
|
if (op_JSR) next_state <= `SEQ_JSR_PUSH;
|
else if (op_JMP) next_state <= `SEQ_JMP_LOAD_PC;
|
else if (op_JMP) next_state <= `SEQ_JMP_LOAD_PC;
|
else
|
else
|
begin
|
begin
|
k_mem_dest <= `MEMDEST_MH; // operand to memlo/memhi
|
if (dec_o_operand_read)
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
|
(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
|
Line 610... |
Line 617... |
state <= `SEQ_PC_READ_H; // loads address
|
state <= `SEQ_PC_READ_H; // loads address
|
if (op_JSR) next_state <= `SEQ_JSR_PUSH;
|
if (op_JSR) next_state <= `SEQ_JSR_PUSH;
|
else if (op_JMP) next_state <= `SEQ_JMP_LOAD_PC;
|
else if (op_JMP) next_state <= `SEQ_JMP_LOAD_PC;
|
else
|
else
|
begin
|
begin
|
k_mem_dest <= `MEMDEST_MH; // operand to memlo/memhi
|
if (dec_o_operand_read)
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
|
(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
|
Line 639... |
Line 644... |
else
|
else
|
next_state <= `SEQ_JMP_LOAD_PC;
|
next_state <= `SEQ_JMP_LOAD_PC;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
`SEQ_DECODE_P23:
|
|
begin // has prefix 10 or 11
|
|
case (dec_o_p1_mode)
|
|
`NONE: // unknown k_opcode... re-fetch ?
|
|
if (op_EXG) begin k_write_exg <= 1; state <= `SEQ_TFREXG; end
|
|
else if (op_TFR) begin k_write_tfr <= 1; state <= `SEQ_TFREXG; end
|
|
else
|
|
state <= `SEQ_FETCH;
|
|
`IMMEDIATE: // 8 or 16 bits as result decides..
|
|
begin
|
|
next_state <= `SEQ_GRAL_ALU;
|
|
if (dec_o_alu_size)
|
|
state <= `SEQ_PC_READ_H;
|
|
else
|
|
state <= `SEQ_PC_READ_L;
|
|
end
|
|
`INHERENT:
|
|
if (op_SWI) state <= (k_p2_valid) ? `SEQ_SWI2:`SEQ_SWI3;
|
|
else state <= `SEQ_GRAL_ALU;
|
|
`DIRECT:
|
|
begin
|
|
state <= `SEQ_PC_READ_L;
|
|
k_mem_dest <= `MEMDEST_MH; // operand to memlo/memhi
|
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
|
(dec_o_left_path_addr == `RN_MEM8))
|
|
begin
|
|
next_state <= `SEQ_MEM_READ_H;
|
|
next_mem_state <= `SEQ_GRAL_ALU; // read then alu
|
|
end
|
|
else
|
|
next_state <= `SEQ_GRAL_ALU; // no read
|
|
k_eahi <= regs_o_dp;
|
|
end
|
|
`INDEXED:
|
|
state <= `SEQ_IND_READ_EA;
|
|
`EXTENDED:
|
|
begin
|
|
state <= `SEQ_PC_READ_H; // loads address
|
|
k_mem_dest <= `MEMDEST_MH; // operand to memlo/memhi
|
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
|
(dec_o_left_path_addr == `RN_MEM8))
|
|
begin
|
|
next_state <= `SEQ_MEM_READ_H;
|
|
next_mem_state <= `SEQ_GRAL_ALU; // read then alu
|
|
end
|
|
else
|
|
next_state <= `SEQ_GRAL_ALU; // no read
|
|
end
|
|
`REL16:
|
|
begin // long branches only
|
|
state <= `SEQ_PC_READ_H; // loads address
|
|
next_state <= `SEQ_JMP_LOAD_PC;
|
|
end
|
|
endcase
|
|
end
|
|
`SEQ_GRAL_ALU:
|
`SEQ_GRAL_ALU:
|
begin
|
begin
|
if (!k_mul_cnt)
|
if (!k_mul_cnt)
|
begin
|
begin
|
state <= `SEQ_GRAL_WBACK;
|
state <= `SEQ_GRAL_WBACK;
|
Line 707... |
Line 657... |
end
|
end
|
`SEQ_GRAL_WBACK:
|
`SEQ_GRAL_WBACK:
|
begin
|
begin
|
next_mem_state <= `SEQ_FETCH;
|
next_mem_state <= `SEQ_FETCH;
|
if (op_CWAI) state <= `SEQ_CWAI_STACK; // CWAI
|
if (op_CWAI) state <= `SEQ_CWAI_STACK; // CWAI
|
|
else if (dec_o_dest_memtype == `MT_BYTE) state <= `SEQ_MEM_WRITE_L;
|
|
else if (dec_o_dest_memtype == `MT_WORD) state <= `SEQ_MEM_WRITE_H;
|
else
|
else
|
case (dec_o_dest_reg_addr)
|
|
`RN_MEM8: state <= `SEQ_MEM_WRITE_L;
|
|
`RN_MEM16: state <= `SEQ_MEM_WRITE_H;
|
|
default:
|
|
begin
|
begin
|
state <= `SEQ_FETCH;
|
state <= `SEQ_FETCH;
|
k_write_post_incdec <= dec_o_ea_wpost & (dec_o_p1_mode == `INDEXED);
|
k_write_post_incdec <= dec_o_ea_wpost & (dec_o_p1_mode == `INDEXED);
|
end
|
end
|
endcase
|
|
end
|
end
|
`SEQ_CWAI_STACK:
|
`SEQ_CWAI_STACK:
|
begin
|
begin
|
k_pp_regs <= 8'hff;
|
k_pp_regs <= 8'hff;
|
k_set_e <= 1;
|
k_set_e <= 1;
|
Line 834... |
Line 781... |
else
|
else
|
if (op_JSR) // jsr
|
if (op_JSR) // jsr
|
next_state <= `SEQ_JSR_PUSH;
|
next_state <= `SEQ_JSR_PUSH;
|
else
|
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_operand_read)
|
(dec_o_left_path_addr == `RN_MEM8))
|
|
begin
|
begin
|
k_mem_dest <= `MEMDEST_MH; // operand lands 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;
|
if (dec_o_ea_indirect)
|
if (dec_o_ea_indirect)
|
k_forced_mem_size <= 1; // to load indirect address
|
k_forced_mem_size <= 1; // to load indirect address
|
end
|
end
|
Line 853... |
Line 798... |
begin
|
begin
|
if (op_JSR) // jsr
|
if (op_JSR) // jsr
|
next_state <= `SEQ_JSR_PUSH;
|
next_state <= `SEQ_JSR_PUSH;
|
else
|
else
|
begin
|
begin
|
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) ||
|
if (dec_o_operand_read)
|
(dec_o_left_path_addr == `RN_MEM8))
|
|
begin
|
begin
|
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;
|
if (dec_o_ea_indirect)
|
if (dec_o_ea_indirect)
|
k_forced_mem_size <= 1; // to load indirect address
|
k_forced_mem_size <= 1; // to load indirect address
|
end
|
end
|
Line 905... |
Line 848... |
end
|
end
|
`SEQ_PREPULL:
|
`SEQ_PREPULL:
|
begin
|
begin
|
if (k_pp_regs != 8'h0)
|
if (k_pp_regs != 8'h0)
|
begin
|
begin
|
k_mem_dest <= `MEMDEST_MH;
|
|
next_mem_state <= `SEQ_PREPULL;
|
next_mem_state <= `SEQ_PREPULL;
|
end
|
end
|
else
|
else
|
state <= `SEQ_FETCH; // end of sequence
|
state <= `SEQ_FETCH; // end of sequence
|
if (k_pp_regs[0]) begin k_pp_active_reg <= `RN_CC; k_pp_regs[0] <= 0; state <= `SEQ_MEM_READ_L; end
|
if (k_pp_regs[0]) begin k_pp_active_reg <= `RN_CC; k_pp_regs[0] <= 0; state <= `SEQ_MEM_READ_L; end
|
Line 1038... |
Line 980... |
k_cpu_oe <= 1; // read
|
k_cpu_oe <= 1; // read
|
state <= `SEQ_MEM_READ_H_2;
|
state <= `SEQ_MEM_READ_H_2;
|
end
|
end
|
`SEQ_MEM_READ_H_2:
|
`SEQ_MEM_READ_H_2:
|
begin
|
begin
|
case (k_mem_dest)
|
k_memhi <= cpu_data_i;
|
`MEMDEST_PC,//: k_new_pc[15:8] <= cpu_data_i;
|
|
`MEMDEST_MH: k_memhi <= cpu_data_i;
|
|
`MEMDEST_AH: k_eahi <= cpu_data_i;
|
|
endcase
|
|
state <= `SEQ_MEM_READ_L_1;
|
state <= `SEQ_MEM_READ_L_1;
|
k_cpu_addr <= k_cpu_addr + 16'h1;
|
k_cpu_addr <= k_cpu_addr + 16'h1;
|
if (op_PULL | op_RTI | op_RTS)
|
if (op_PULL | op_RTI | op_RTS)
|
k_inc_su <= 1;
|
k_inc_su <= 1;
|
end
|
end
|
Line 1065... |
Line 1003... |
k_cpu_oe <= 1; // read
|
k_cpu_oe <= 1; // read
|
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)
|
k_memlo <= cpu_data_i;
|
`MEMDEST_PC,
|
|
`MEMDEST_MH: k_memlo <= cpu_data_i;
|
|
`MEMDEST_AH: k_ealo <= cpu_data_i;
|
|
endcase
|
|
if (op_PULL | op_RTI | op_RTS) k_write_dest <= 1; // FIXME: which other opcode is inherent and needs write-back ?
|
if (op_PULL | op_RTI | op_RTS) k_write_dest <= 1; // FIXME: which other opcode is inherent and needs write-back ?
|
|
if (next_mem_state == `SEQ_LOADPC) // used by cold-reset
|
if (next_mem_state == `SEQ_LOADPC)
|
|
k_write_pc <= 1;
|
k_write_pc <= 1;
|
case (dec_o_p1_mode)
|
case (dec_o_p1_mode)
|
`INDEXED: // address loaded, load argument
|
`INDEXED: // address loaded, load argument
|
if (k_indirect_loaded | (!dec_o_ea_indirect))
|
if (k_indirect_loaded | (!dec_o_ea_indirect))
|
state <= next_mem_state;
|
state <= next_mem_state;
|
Line 1125... |
Line 1058... |
end
|
end
|
end
|
end
|
|
|
initial
|
initial
|
begin
|
begin
|
|
k_mem_state = 0;
|
k_cpu_oe = 0;
|
k_cpu_oe = 0;
|
k_cpu_we = 0;
|
k_cpu_we = 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;
|
k_write_dest = 0;
|
k_indirect_loaded = 0;
|
k_indirect_loaded = 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
|