Line 45... |
Line 45... |
* Decoder outputs
|
* Decoder outputs
|
*/
|
*/
|
wire [2:0] dec_o_p1_mode; // addressing mode
|
wire [2:0] dec_o_p1_mode; // addressing mode
|
wire [2:0] dec_o_p1_optype; // k_opcode type
|
wire [2:0] dec_o_p1_optype; // k_opcode type
|
wire dec_o_use_s; // signals when S should be used instead of U
|
wire dec_o_use_s; // signals when S should be used instead of U
|
wire dec_o_alu_size;
|
wire dec_o_alu_size; /* size of the result of an alu opcode (destination to be written) */
|
/* 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_ofs0, dec_o_ea_indirect;
|
/* 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 */
|
Line 100... |
Line 100... |
regblock regs(
|
regblock regs(
|
.clk_in(cpu_clk),
|
.clk_in(cpu_clk),
|
.path_left_addr(datamux_o_alu_in_left_path_addr),
|
.path_left_addr(datamux_o_alu_in_left_path_addr),
|
.path_right_addr(dec_o_right_path_addr),
|
.path_right_addr(dec_o_right_path_addr),
|
.write_reg_addr(datamux_o_dest_reg_addr),
|
.write_reg_addr(datamux_o_dest_reg_addr),
|
.exg_dest_r(k_postbyte[3:0]),
|
.exg_dest_r(k_postbyte[7:4]),
|
.eapostbyte( k_ind_ea ),
|
.eapostbyte( k_ind_ea ),
|
.offset16({ k_ofshi, k_ofslo }),
|
.offset16({ k_ofshi, k_ofslo }),
|
.write_reg(k_write_dest),
|
.write_reg(k_write_dest),
|
.write_tfr(k_write_tfr),
|
.write_tfr(k_write_tfr),
|
.write_exg(k_write_exg),
|
.write_exg(k_write_exg),
|
Line 198... |
Line 198... |
begin
|
begin
|
if (k_pp_active_reg != `RN_INV)
|
if (k_pp_active_reg != `RN_INV)
|
datamux_o_alu_in_left_path_addr = k_pp_active_reg;
|
datamux_o_alu_in_left_path_addr = k_pp_active_reg;
|
else
|
else
|
datamux_o_alu_in_left_path_addr = dec_o_left_path_addr;
|
datamux_o_alu_in_left_path_addr = dec_o_left_path_addr;
|
|
|
/*
|
|
case (k_pp_active_reg)
|
|
8'h80: datamux_o_alu_in_left_path_addr = `RN_PC;
|
|
8'h40: datamux_o_alu_in_left_path_addr = (dec_o_use_s) ? `RN_U:`RN_S;
|
|
8'h20: datamux_o_alu_in_left_path_addr = `RN_IY;
|
|
8'h10: datamux_o_alu_in_left_path_addr = `RN_IX;
|
|
8'h08: datamux_o_alu_in_left_path_addr = `RN_DP;
|
|
8'h04: datamux_o_alu_in_left_path_addr = `RN_ACCB;
|
|
8'h02: datamux_o_alu_in_left_path_addr = `RN_ACCA;
|
|
8'h01: datamux_o_alu_in_left_path_addr = `RN_CC;
|
|
8'h00: datamux_o_alu_in_left_path_addr = dec_o_left_path_addr;
|
|
endcase
|
|
*/
|
|
end
|
end
|
|
|
/* Destination register address MUX
|
/* Destination register address MUX
|
*/
|
*/
|
always @(*)
|
always @(*)
|
begin
|
begin
|
if (k_pp_active_reg != `RN_INV)
|
if (k_pp_active_reg != `RN_INV)
|
datamux_o_dest_reg_addr = k_pp_active_reg;
|
datamux_o_dest_reg_addr = k_pp_active_reg;
|
else
|
else
|
datamux_o_dest_reg_addr = dec_o_dest_reg_addr;
|
datamux_o_dest_reg_addr = dec_o_dest_reg_addr;
|
/*
|
|
case (k_pp_active_reg)
|
|
8'h80: datamux_o_dest_reg_addr = `RN_PC;
|
|
8'h40: datamux_o_dest_reg_addr = (dec_o_use_s) ? `RN_U:`RN_S;
|
|
8'h20: datamux_o_dest_reg_addr = `RN_IY;
|
|
8'h10: datamux_o_dest_reg_addr = `RN_IX;
|
|
8'h08: datamux_o_dest_reg_addr = `RN_DP;
|
|
8'h04: datamux_o_dest_reg_addr = `RN_ACCB;
|
|
8'h02: datamux_o_dest_reg_addr = `RN_ACCA;
|
|
8'h01: datamux_o_dest_reg_addr = `RN_CC;
|
|
8'h00: datamux_o_dest_reg_addr = dec_o_dest_reg_addr;
|
|
endcase
|
|
*/
|
|
end
|
end
|
|
|
/* Destination register data mux
|
/* Destination register data mux
|
* selects the source to write to register. 16 bit registers have to be written at once after reading the low byte
|
* selects the source to write to register. 16 bit registers have to be written at once after reading the low byte
|
*
|
*
|
Line 286... |
Line 259... |
`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;
|
|
|
endcase
|
endcase
|
end
|
end
|
/* ALU right input mux */
|
/* ALU right input mux */
|
always @(*)
|
always @(*)
|
begin
|
begin
|
Line 366... |
Line 338... |
next_mem_state <= `SEQ_LOADPC;
|
next_mem_state <= `SEQ_LOADPC;
|
end
|
end
|
`SEQ_NMI:
|
`SEQ_NMI:
|
begin
|
begin
|
k_forced_mem_size <= 1;
|
k_forced_mem_size <= 1;
|
k_reg_nmi <= 2'h0;
|
k_reg_nmi <= 3'h0;
|
{ k_eahi, k_ealo } <= 16'hfffc;
|
{ k_eahi, k_ealo } <= 16'hfffc;
|
k_pp_regs <= 8'hff;
|
k_pp_regs <= 8'hff;
|
k_set_e <= 1;
|
k_set_e <= 1;
|
state <= `SEQ_PREPUSH; // first stack the registers
|
state <= `SEQ_PREPUSH; // first stack the registers
|
next_push_state <= `SEQ_MEM_READ_H; // than load new PC
|
next_push_state <= `SEQ_MEM_READ_H; // than load new PC
|
Line 388... |
Line 360... |
k_set_e <= 1;
|
k_set_e <= 1;
|
end
|
end
|
`SEQ_IRQ:
|
`SEQ_IRQ:
|
begin
|
begin
|
k_forced_mem_size <= 1;
|
k_forced_mem_size <= 1;
|
k_reg_irq <= 2'h0;
|
k_reg_irq <= 3'h0;
|
state <= `SEQ_MEM_READ_H;
|
state <= `SEQ_MEM_READ_H;
|
{ k_eahi, k_ealo } <= 16'hfff8;
|
{ k_eahi, k_ealo } <= 16'hfff8;
|
k_pp_regs <= 8'hff;
|
k_pp_regs <= 8'hff;
|
next_mem_state <= `SEQ_PREPUSH;
|
next_mem_state <= `SEQ_PREPUSH;
|
k_set_e <= 1;
|
k_set_e <= 1;
|
Line 401... |
Line 373... |
next_mem_state <= `SEQ_FETCH; // than continue fetching instructions
|
next_mem_state <= `SEQ_FETCH; // than continue fetching instructions
|
end
|
end
|
`SEQ_FIRQ:
|
`SEQ_FIRQ:
|
begin
|
begin
|
k_forced_mem_size <= 1;
|
k_forced_mem_size <= 1;
|
k_reg_firq <= 2'h0;
|
k_reg_firq <= 3'h0;
|
{ k_eahi, k_ealo } <= 16'hfff6;
|
{ k_eahi, k_ealo } <= 16'hfff6;
|
k_pp_regs <= 8'h81; // PC & CC
|
k_pp_regs <= 8'h81; // PC & CC
|
k_clear_e <= 1;
|
k_clear_e <= 1;
|
state <= `SEQ_PREPUSH; // first stack the registers
|
state <= `SEQ_PREPUSH; // first stack the registers
|
next_push_state <= `SEQ_MEM_READ_H; // than load new PC
|
next_push_state <= `SEQ_MEM_READ_H; // than load new PC
|
Line 449... |
Line 421... |
`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;
|
else
|
else
|
if (k_firq_req)
|
if (k_firq_req & `FLAGF)
|
state <= `SEQ_FIRQ;
|
state <= `SEQ_FIRQ;
|
else
|
else
|
if (k_irq_req)
|
if (k_irq_req & `FLAGI)
|
state <= `SEQ_IRQ;
|
state <= `SEQ_IRQ;
|
else
|
else
|
begin
|
begin
|
state <= `SEQ_FETCH_1;
|
state <= `SEQ_FETCH_1;
|
k_cpu_addr <= regs_o_pc;
|
k_cpu_addr <= regs_o_pc;
|
Line 673... |
Line 645... |
if (!k_mul_cnt)
|
if (!k_mul_cnt)
|
begin
|
begin
|
state <= `SEQ_GRAL_WBACK;
|
state <= `SEQ_GRAL_WBACK;
|
k_write_dest <= 1; /* write destination on wback */
|
k_write_dest <= 1; /* write destination on wback */
|
end
|
end
|
else
|
|
k_mul_cnt <= 1'h0;
|
k_mul_cnt <= 1'h0;
|
end
|
end
|
`SEQ_GRAL_WBACK:
|
`SEQ_GRAL_WBACK:
|
begin
|
begin
|
next_mem_state <= `SEQ_FETCH;
|
next_mem_state <= `SEQ_FETCH;
|
Line 708... |
Line 679... |
next_mem_state <= `SEQ_FETCH; // then continue fetching instructions
|
next_mem_state <= `SEQ_FETCH; // then continue fetching instructions
|
k_eahi <= 8'hff;
|
k_eahi <= 8'hff;
|
k_ealo[7:4] <= 4'hf;
|
k_ealo[7:4] <= 4'hf;
|
if (k_nmi_req)
|
if (k_nmi_req)
|
begin
|
begin
|
k_reg_nmi <= 2'h0;
|
k_reg_nmi <= 3'h0;
|
k_ealo[3:0] <= 4'hc;
|
k_ealo[3:0] <= 4'hc;
|
state <= `SEQ_MEM_READ_H; // load new PC
|
state <= `SEQ_MEM_READ_H; // load new PC
|
end
|
end
|
else
|
else
|
if (k_firq_req)
|
if (k_firq_req & `FLAGF)
|
begin
|
begin
|
k_reg_firq <= 2'h0;
|
k_reg_firq <= 3'h0;
|
k_ealo[3:0] <= 4'h6;
|
k_ealo[3:0] <= 4'h6;
|
state <= `SEQ_MEM_READ_H; // load new PC
|
state <= `SEQ_MEM_READ_H; // load new PC
|
end
|
end
|
else
|
else
|
if (k_irq_req)
|
if (k_irq_req & `FLAGI)
|
begin
|
begin
|
k_reg_irq <= 2'h0;
|
k_reg_irq <= 3'h0;
|
k_ealo[3:0] <= 4'hf8;
|
k_ealo[3:0] <= 4'hf8;
|
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:
|
|
* waits for an interrupt request
|
|
* we recognize an interrupt if the level was kept for 2 cycles
|
|
* then we don't call the service routine
|
|
* if it was 3 or more cycles, then we call the service routine
|
|
*/
|
|
begin
|
|
if (k_nmi_req)
|
|
begin
|
|
if (k_reg_nmi == 3'b111) // at least 3 cycles long
|
|
state <= `SEQ_NMI;
|
|
else
|
|
begin
|
|
state <= `SEQ_FETCH;
|
|
k_reg_nmi <= 3'h0;
|
|
end
|
|
end
|
|
else
|
|
if (k_firq_req & `FLAGF)
|
|
begin
|
|
if (k_reg_firq == 3'b111) // at least 3 cycles long
|
|
state <= `SEQ_FIRQ;
|
|
else
|
|
begin
|
|
state <= `SEQ_FETCH;
|
|
k_reg_firq <= 3'h0;
|
|
end
|
|
end
|
|
else
|
|
if (k_irq_req & `FLAGI)
|
|
begin
|
|
if (k_reg_irq == 3'b111) // at least 3 cycles long
|
|
state <= `SEQ_IRQ;
|
|
else
|
|
begin
|
|
state <= `SEQ_FETCH;
|
|
k_reg_irq <= 3'h0;
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
state <= `SEQ_FETCH_1;
|
|
k_cpu_addr <= regs_o_pc;
|
|
end
|
|
end
|
`SEQ_TFREXG:
|
`SEQ_TFREXG:
|
state <= `SEQ_FETCH;
|
state <= `SEQ_FETCH;
|
`SEQ_IND_READ_EA: // reads EA byte
|
`SEQ_IND_READ_EA: // reads EA byte
|
begin
|
begin
|
k_cpu_addr <= regs_o_pc;
|
k_cpu_addr <= regs_o_pc;
|