URL
https://opencores.org/ocsvn/6809_6309_compatible_core/6809_6309_compatible_core/trunk
Subversion Repositories 6809_6309_compatible_core
Compare Revisions
- This comparison shows the changes necessary to convert path
/6809_6309_compatible_core/trunk
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/rtl/verilog/MC6809_cpu.v
0,0 → 1,953
/* |
* |
* MC6809/HD6309 Compatible code |
* (c) 2013 R.A. Paz Schmidt |
* distributed under the terms of the Lesser GPL, see LICENSE.TXT |
* |
*/ |
|
`include "defs.v" |
module MC6809_cpu( |
input wire cpu_clk, |
input wire cpu_reset, |
input wire cpu_nmi_n, |
input wire cpu_irq_n, |
input wire cpu_firq_n, |
output wire [5:0] cpu_state_o, |
output wire cpu_we_o, |
output wire cpu_oe_o, |
output wire [15:0] cpu_addr_o, |
input wire [7:0] cpu_data_i, |
output wire [7:0] cpu_data_o |
); |
|
wire k_reset; |
wire k_clk; |
assign k_clk = cpu_clk; |
|
reg [7:0] k_opcode, k_postbyte0, k_ind_ea; /* all bytes of an instruction */ |
reg [7:0] k_pp_regs, k_pp_active_reg; // push/pull mask |
reg [7:0] k_memhi, k_memlo, k_cpu_data_o; /* operand read from memory */ |
reg [7:0] k_ofslo, k_ofshi, k_eahi, k_ealo; |
reg [5:0] state, // state of the main state machine |
next_state, // next state to exit to from the read from [PC] state machine |
next_mem_state, // next state to exit to from the read from memory state machine |
next_push_state; // next state to exit to from push multiple state machine |
reg k_cpu_oe, k_cpu_we, k_inc_pc, k_pull_reg_write; |
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 [1:0] k_mem_dest; |
reg k_write_post_incdec; // asserted when in the last write cycle or in write back for loads |
/**** |
* Decoder outputs |
*/ |
wire [2:0] dec_o_p1_mode; // addressing mode |
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_alu_size; |
/* ea decoder */ |
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 */ |
wire [4:0] dec_o_alu_opcode; |
wire [1:0] dec_o_right_path_mod; /* Modifier for alu's right path input */ |
/* register decoder */ |
wire dec_o_wdest_8, dec_o_wdest_16, dec_o_write_flags; |
wire [3:0] dec_o_left_path_addr, dec_o_right_path_addr, dec_o_dest_reg_addr; |
/* test condition */ |
wire dec_o_cond_taken; |
/* ALU outputs */ |
wire [15:0] alu_o_result; |
wire [7:0] alu_o_CCR; |
/* Register Module outputs */ |
wire [15:0] regs_o_left_path_data, regs_o_right_path_data, regs_o_eamem_addr, regs_o_su; |
wire [7:0] regs_o_dp; |
wire [15:0] regs_o_pc; |
wire [7:0] regs_o_CCR; |
/* Data Muxes */ |
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 k_p2_valid, k_p3_valid; /* 1 when k_postbyte0 has been loaded for page 2 or page 3 */ |
|
/* Interrupt sync registers */ |
|
reg [2:0] k_reg_nmi, k_reg_irq, k_reg_firq; |
wire k_nmi_req, k_firq_req, k_irq_req; |
|
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_irq_req = k_reg_irq[2] & k_reg_irq[1]; |
|
alu16 alu( |
.clk(k_clk), |
.a_in(datamux_o_alu_in_left_path_data), |
.b_in(datamux_o_alu_in_right_path_data), |
.CCR(regs_o_CCR), /* flags */ |
.opcode_in(dec_o_alu_opcode), /* ALU k_opcode */ |
.sz_in(dec_o_alu_size), /* size, low 8 bit, high 16 bit */ |
.q_out(alu_o_result), /* ALU result */ |
.CCRo(alu_o_CCR) |
); |
|
regblock regs( |
.clk_in(k_clk), |
.path_left_addr(datamux_o_alu_in_left_path_addr), |
.path_right_addr(dec_o_right_path_addr), |
.write_reg_addr(datamux_o_dest_reg_addr), |
.eapostbyte( k_ind_ea ), |
.offset16({ k_ofshi, k_ofslo }), |
.write_reg_8(dec_o_wdest_8 & (state == `SEQ_GRAL_WBACK)), |
.write_reg_16(dec_o_wdest_16 & (state == `SEQ_GRAL_WBACK)), |
.write_pull_reg(k_pull_reg_write), |
.write_post(k_write_post_incdec), |
.write_pc(k_write_pc), |
.inc_pc(k_inc_pc), |
.inc_su(k_inc_su), |
.dec_su(k_dec_su), |
.use_s(dec_o_use_s), |
.data_w(datamux_o_dest), |
.new_pc(k_new_pc), |
.CCR_in(alu_o_CCR), |
.write_flags(dec_o_write_flags & (state == `SEQ_GRAL_WBACK)), |
.set_e(k_set_e), |
.clear_e(k_clear_e), |
.CCR_o(regs_o_CCR), |
.path_left_data(regs_o_left_path_data), |
.path_right_data(regs_o_right_path_data), |
.eamem_addr(regs_o_eamem_addr), |
.reg_pc(regs_o_pc), |
.reg_dp(regs_o_dp), |
.reg_su(regs_o_su) |
); |
|
decode_regs dec_regs( |
.opcode(k_opcode), |
.postbyte0(k_postbyte0), |
.page2_valid(k_p2_valid), |
.page3_valid(k_p3_valid), |
.path_left_addr(dec_o_left_path_addr), |
.path_right_addr(dec_o_right_path_addr), |
.dest_reg(dec_o_dest_reg_addr), |
.write_dest_8(dec_o_wdest_8), |
.write_dest_16(dec_o_wdest_16), |
.result_size(dec_o_alu_size) |
); |
|
decode_op dec_op( |
.opcode(k_opcode), |
.postbyte0(k_postbyte0), |
.page2_valid(k_p2_valid), |
.page3_valid(k_p3_valid), |
.mode(dec_o_p1_mode), |
.optype(dec_o_p1_optype), |
.use_s(dec_o_use_s) |
); |
|
decode_ea dec_ea( |
.eapostbyte( k_ind_ea ), |
.noofs(dec_o_ea_ofs0), |
.ofs8(dec_o_ea_ofs8), |
.ofs16(dec_o_ea_ofs16), |
.write_post(dec_o_ea_wpost), |
.isind(dec_o_ea_indirect) |
); |
|
/* Opcodes for the ALU are decoded here |
* Write Flags are also decoded here |
*/ |
decode_alu dec_alu( |
.opcode(k_opcode), |
.postbyte0(k_postbyte0), |
.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 */ |
test_condition test_cond( |
.opcode(k_opcode), |
.postbyte0(k_postbyte0), |
.page2_valid(k_p2_valid), |
.CCR(regs_o_CCR), |
.cond_taken(dec_o_cond_taken) |
); |
|
/* Module IO */ |
|
assign cpu_oe_o = k_cpu_oe; // we latch on the rising edge |
assign cpu_we_o = k_cpu_we; |
assign cpu_addr_o = k_cpu_addr; |
assign cpu_data_o = k_cpu_data_o; |
assign k_reset = cpu_reset; |
assign cpu_state_o = state; |
|
|
/* Left Register read mux |
*/ |
always @(*) |
begin |
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; |
endcase |
end |
|
/* Destination register address MUX |
*/ |
always @(*) |
begin |
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; |
endcase |
end |
|
/* 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 |
* |
*/ |
always @(*) |
begin |
datamux_o_dest = alu_o_result; |
case (dec_o_p1_optype) |
`OP_PULL, `OP_RTS: // destination register |
datamux_o_dest = { k_memhi, k_memlo }; |
`OP_LEA: |
if (dec_o_ea_indirect & dec_o_alu_size) |
datamux_o_dest = { k_memhi, k_memlo }; |
else |
datamux_o_dest = regs_o_eamem_addr; |
endcase |
end |
|
/* ALU left input mux */ |
|
always @(*) |
begin |
if (dec_o_left_path_addr == `RN_MEM8) |
datamux_o_alu_in_left_path_data = { k_memhi, k_memlo }; |
else |
begin |
datamux_o_alu_in_left_path_data = regs_o_left_path_data; |
end |
end |
|
/* ALU right input mux */ |
always @(*) |
begin |
case (dec_o_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 }; |
`RN_IMM8: |
datamux_o_alu_in_right_path_data = { 8'h0, k_memlo }; |
`RN_IMM16: |
datamux_o_alu_in_right_path_data = { k_memhi, k_memlo }; |
default: |
case (dec_o_right_path_mod) |
`MOD_DEFAULT: datamux_o_alu_in_right_path_data = regs_o_right_path_data; |
`MOD_ONE: datamux_o_alu_in_right_path_data = 16'h0001; |
`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 |
|
always @(posedge k_clk or posedge k_reset) |
begin |
if (k_reset == 1'b1) |
begin |
state <= `SEQ_COLDRESET; |
k_reg_nmi <= 0; |
k_reg_firq <= 0; |
k_reg_irq <= 0; |
end |
else |
begin |
/* Inrerrupt recognition and acknowledge */ |
if (!k_reg_nmi[2]) |
k_reg_nmi <= { k_reg_nmi[1:0], cpu_nmi_n }; |
if (!k_reg_irq[2]) |
k_reg_irq <= { k_reg_irq[1:0], cpu_irq_n }; |
if (!k_reg_firq[2]) |
k_reg_firq <= { k_reg_firq[1:0], cpu_firq_n }; |
/* modifier registers */ |
if (k_inc_pc) |
k_inc_pc <= 0; |
if (k_write_pc) |
k_write_pc <= 0; |
if (k_cpu_we) |
k_cpu_we <= 0; |
if (k_cpu_oe) |
k_cpu_oe <= 0; |
if (k_write_post_incdec) |
k_write_post_incdec <= 0; |
if (k_dec_su) |
k_dec_su <= 0; |
if (k_inc_su) |
k_inc_su <= 0; |
if (k_pull_reg_write) |
k_pull_reg_write <= 0; |
if (k_set_e) |
k_set_e <= 0; |
if (k_clear_e) |
k_clear_e <= 0; |
case (state) |
`SEQ_COLDRESET: |
begin |
state <= `SEQ_MEM_READ_H; |
k_eahi <= 8'hff; |
k_ealo <= 8'hfe; |
next_mem_state <= `SEQ_LOADPC; |
end |
`SEQ_NMI: |
begin |
k_reg_nmi <= 2'h0; |
{ k_eahi, k_ealo } <= 16'hfffc; |
k_pp_regs <= 8'hff; |
k_set_e <= 1; |
state <= `SEQ_PREPUSH; // first stack the registers |
next_push_state <= `SEQ_MEM_READ_H; // than load new PC |
next_mem_state <= `SEQ_FETCH; // than continue fetching instructions |
end |
`SEQ_SWI: |
begin |
state <= `SEQ_MEM_READ_H; |
{ k_eahi, k_ealo } <= 16'hfffa; |
k_pp_regs <= 8'hff; |
state <= `SEQ_PREPUSH; // first stack the registers |
next_push_state <= `SEQ_MEM_READ_H; // than load new PC |
next_mem_state <= `SEQ_FETCH; // than continue fetching instructions |
k_set_e <= 1; |
end |
`SEQ_IRQ: |
begin |
k_reg_irq <= 2'h0; |
state <= `SEQ_MEM_READ_H; |
{ k_eahi, k_ealo } <= 16'hfff8; |
k_pp_regs <= 8'hff; |
next_mem_state <= `SEQ_PREPUSH; |
k_set_e <= 1; |
state <= `SEQ_PREPUSH; // first stack the registers |
next_push_state <= `SEQ_MEM_READ_H; // than load new PC |
next_mem_state <= `SEQ_FETCH; // than continue fetching instructions |
end |
`SEQ_FIRQ: |
begin |
k_reg_firq <= 2'h0; |
{ k_eahi, k_ealo } <= 16'hfff6; |
k_pp_regs <= 8'h81; // PC & CC |
k_clear_e <= 1; |
state <= `SEQ_PREPUSH; // first stack the registers |
next_push_state <= `SEQ_MEM_READ_H; // than load new PC |
next_mem_state <= `SEQ_FETCH; // than continue fetching instructions |
end |
`SEQ_SWI2: |
begin |
{ k_eahi, k_ealo } <= 16'hfff4; |
k_pp_regs <= 8'hff; |
k_set_e <= 1; |
state <= `SEQ_PREPUSH; // first stack the registers |
next_push_state <= `SEQ_MEM_READ_H; // than load new PC |
next_mem_state <= `SEQ_FETCH; // than continue fetching instructions |
end |
`SEQ_SWI3: |
begin |
{ k_eahi, k_ealo } <= 16'hfff2; |
k_pp_regs <= 8'hff; |
k_set_e <= 1; |
state <= `SEQ_PREPUSH; // first stack the registers |
next_push_state <= `SEQ_MEM_READ_H; // than load new PC |
next_mem_state <= `SEQ_FETCH; // than continue fetching instructions |
end |
`SEQ_UNDEF: |
begin |
{ k_eahi, k_ealo } <= 16'hfff0; |
k_pp_regs <= 8'hff; |
k_set_e <= 1; |
state <= `SEQ_PREPUSH; // first stack the registers |
next_push_state <= `SEQ_MEM_READ_H; // than load new PC |
next_mem_state <= `SEQ_FETCH; // than continue fetching instructions |
end |
`SEQ_LOADPC: /* loads the PC with the address taken from the reset vector */ |
begin |
$display("cpu_data_i %02x %t", cpu_data_i, $time); |
state <= `SEQ_FETCH; |
end |
`SEQ_FETCH: /* execution starts here */ |
begin |
if (k_nmi_req) |
state <= `SEQ_NMI; |
else |
if (k_firq_req) |
state <= `SEQ_FIRQ; |
else |
if (k_irq_req) |
state <= `SEQ_IRQ; |
else |
begin |
state <= `SEQ_FETCH_1; |
k_cpu_addr <= regs_o_pc; |
end |
end |
`SEQ_FETCH_1: |
begin |
k_cpu_oe <= 1; |
state <= `SEQ_FETCH_2; |
end |
`SEQ_FETCH_2: |
begin |
k_opcode <= cpu_data_i; |
case (cpu_data_i[7:0]) /* page 2 & 3 opcodes are recognized here */ |
8'h10: |
begin |
k_p2_valid <= 1; |
k_p3_valid <= 0; |
state <= `SEQ_FETCH_3; |
end |
8'h11: |
begin |
k_p2_valid <= 0; |
k_p3_valid <= 1; |
state <= `SEQ_FETCH_3; |
end |
default: |
begin |
state <= `SEQ_DECODE; |
k_p2_valid <= 0; // set when an k_opcode is page 2 |
k_p3_valid <= 0; // set when an k_opcode is page 3 |
end |
endcase |
k_pp_active_reg <= 8'h00; // prevents wrong register in left/dest data muxes |
k_inc_pc <= 1; |
end |
`SEQ_FETCH_3: |
begin |
state <= `SEQ_FETCH_4; |
k_cpu_addr <= regs_o_pc; |
end |
`SEQ_FETCH_4: |
begin |
k_cpu_oe <= 1; |
state <= `SEQ_FETCH_5; |
end |
`SEQ_FETCH_5: /* fetches a page 2 or 3 opcode */ |
begin |
k_postbyte0 <= cpu_data_i; |
k_inc_pc <= 1; |
state <= `SEQ_DECODE_P23; |
end |
`SEQ_DECODE: |
begin |
/* here we have the first byte of the k_opcode and should be decided to which state we jump |
* inherent means that no extra info is needed |
* ALU opcodes need routing of registers to/from the ALU to the registers |
*/ |
case (dec_o_p1_mode) |
`NONE: // unknown k_opcode and push/pull... refetch ? |
begin |
casex (k_opcode) |
8'h39: // RTS |
begin |
state <= `SEQ_PREPULL; |
k_pp_regs <= 8'h80; // Pull PC (RTS)all regs |
end |
8'h3B: // RTI |
begin |
state <= `SEQ_PREPULL; |
k_pp_regs <= 8'hff; // all regs |
end |
8'b001101x0: // PUSH S&U |
begin |
state <= `SEQ_PC_READ_L; |
next_state <= `SEQ_PREPUSH; |
next_push_state <= `SEQ_FETCH; |
end |
8'b001101x1: // PULL S&U |
begin |
next_state <= `SEQ_PREPULL; |
state <= `SEQ_PC_READ_L; |
end |
default: /* we ignore unknown opcodes */ |
state <= `SEQ_FETCH; |
endcase |
end |
`IMMEDIATE: // 8 or 16 bits as result decides.. |
begin |
if (dec_o_alu_size) |
state <= `SEQ_PC_READ_H; |
else |
state <= `SEQ_PC_READ_L; |
next_state <= `SEQ_GRAL_ALU; |
end |
`INHERENT: |
begin |
case (k_opcode) |
8'h3f: state <= `SEQ_SWI; |
default: state <= `SEQ_GRAL_ALU; |
endcase |
end |
`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 |
if (dec_o_alu_size) |
next_state <= `SEQ_MEM_READ_H; |
else |
next_state <= `SEQ_MEM_READ_L; |
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 |
if (dec_o_alu_size) |
next_state <= `SEQ_MEM_READ_H; |
else |
next_state <= `SEQ_MEM_READ_L; |
next_mem_state <= `SEQ_GRAL_ALU; // read then alu |
end |
else |
next_state <= `SEQ_GRAL_ALU; // no read |
end |
`REL8: |
begin |
state <= `SEQ_PC_READ_L; // loads address |
if (dec_o_p1_optype == `OP_JSR) // bsr |
next_state <= `SEQ_JSR_PUSH; |
else |
next_state <= `SEQ_JMP_LOAD_PC; // offset loaded in this cycle, jump if needed |
end |
`REL16: |
begin |
state <= `SEQ_PC_READ_H; // loads address |
if (dec_o_p1_optype == `OP_JSR) // lbsr |
next_state <= `SEQ_JSR_PUSH; |
else |
next_state <= `SEQ_JMP_LOAD_PC; |
end |
endcase |
end |
`SEQ_DECODE_P23: |
begin // has prefix 10 or 11 |
k_inc_pc <= 0; |
case (dec_o_p1_mode) |
`NONE: // unknown k_opcode... re-fetch ? |
state <= `SEQ_FETCH; |
`IMMEDIATE: // 8 or 16 bits as result decides.. |
begin |
if (dec_o_alu_size) |
state <= `SEQ_PC_READ_H; |
else |
state <= `SEQ_PC_READ_L; |
next_state <= `SEQ_GRAL_ALU; |
end |
`INHERENT: |
case (k_opcode) |
8'h3f: if (k_p2_valid) state <= `SEQ_SWI2; |
else state <= `SEQ_SWI3; |
default: state <= `SEQ_GRAL_ALU; |
endcase |
`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 |
if (dec_o_alu_size) |
next_state <= `SEQ_MEM_READ_H; |
else |
next_state <= `SEQ_MEM_READ_L; |
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 |
if (dec_o_alu_size) |
next_state <= `SEQ_MEM_READ_H; |
else |
next_state <= `SEQ_MEM_READ_L; |
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: |
state <= `SEQ_GRAL_WBACK; |
`SEQ_GRAL_WBACK: |
begin |
next_mem_state <= `SEQ_FETCH; |
case (dec_o_dest_reg_addr) |
`RN_MEM8: state <= `SEQ_MEM_WRITE_L; |
`RN_MEM16: state <= `SEQ_MEM_WRITE_H; |
default: |
begin |
state <= `SEQ_FETCH; |
k_write_post_incdec <= dec_o_ea_wpost; |
end |
endcase |
end |
`SEQ_INH_ALU: |
state <= `SEQ_GRAL_WBACK; |
`SEQ_IND_READ_EA: // reads EA byte |
begin |
k_cpu_addr <= regs_o_pc; |
state <= `SEQ_IND_READ_EA_1; |
k_inc_pc <= 1; |
end |
`SEQ_IND_READ_EA_1: |
begin |
k_cpu_oe <= 1; // read |
state <= `SEQ_IND_READ_EA_2; |
end |
`SEQ_IND_READ_EA_2: |
begin |
k_ind_ea <= cpu_data_i; |
state <= `SEQ_IND_DECODE; |
end |
`SEQ_IND_DECODE: // here we have to see what we need for indexed... |
begin |
if (dec_o_ea_ofs8) |
begin // load 1 byte offset |
state <= `SEQ_PC_READ_L; |
next_state <= `SEQ_IND_DECODE_OFS; // has some offset, load arg |
end |
else |
if (dec_o_ea_ofs16) |
begin // load 2 bytes offset |
state <= `SEQ_PC_READ_H; |
next_state <= `SEQ_IND_DECODE_OFS; // has some offset, load arg |
end |
else |
//if (dec_o_ea_ofs0) |
begin // no extra load... |
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) || |
(dec_o_left_path_addr == `RN_MEM8)) |
begin |
k_mem_dest <= `MEMDEST_MH; // operand land in k_memhi/lo |
next_mem_state <= `SEQ_GRAL_ALU; |
if (dec_o_alu_size) |
state <= `SEQ_MEM_READ_H; |
else |
state <= `SEQ_MEM_READ_L; |
end |
else |
state <= `SEQ_GRAL_ALU; // no load, then store |
end |
end |
`SEQ_IND_DECODE_OFS: // loads argument if needed |
begin |
if ((dec_o_right_path_addr == `RN_MEM8) || (dec_o_right_path_addr == `RN_MEM16) || |
(dec_o_left_path_addr == `RN_MEM8)) |
begin |
k_mem_dest <= `MEMDEST_MH; // operand land in k_memhi/lo |
next_mem_state <= `SEQ_GRAL_ALU; |
if (dec_o_alu_size) |
state <= `SEQ_MEM_READ_H; |
else |
state <= `SEQ_MEM_READ_L; |
end |
else |
state <= `SEQ_GRAL_ALU; // no load, then store |
end |
`SEQ_JMP_LOAD_PC: |
begin |
case (dec_o_p1_mode) |
`REL16: |
begin |
k_new_pc <= regs_o_pc + { k_memhi,k_memlo }; |
if (dec_o_cond_taken) |
k_write_pc <= 1; |
end |
`REL8: |
begin |
k_new_pc <= regs_o_pc + { {8{k_memlo[7]}}, k_memlo }; |
if (dec_o_cond_taken) |
k_write_pc <= 1; |
end |
`EXTENDED: |
begin |
k_new_pc <= { k_eahi,k_ealo }; |
k_write_pc <= 1; |
end |
`DIRECT: |
begin |
k_new_pc <= { regs_o_dp, k_ealo }; |
k_write_pc <= 1; |
end |
`INDEXED: |
begin |
if (dec_o_ea_indirect) |
k_new_pc <= { k_memhi,k_memlo }; |
else |
k_new_pc <= regs_o_eamem_addr; |
k_write_pc <= 1; |
end |
endcase |
state <= `SEQ_FETCH; |
|
end |
`SEQ_JSR_PUSH: |
begin |
k_pp_active_reg <= 8'h80; // push PC |
state <= `SEQ_PUSH_WRITE_L; |
next_state <= `SEQ_JMP_LOAD_PC; |
end |
`SEQ_PREPUSH: |
begin |
next_state <= `SEQ_PREPUSH; |
if (k_pp_regs > 0) |
state <= `SEQ_PUSH_WRITE_L; |
else |
state <= next_push_state; |
if (k_pp_regs[7]) begin k_pp_regs[7] <= 0; k_pp_active_reg <= 8'h80; end |
else |
if (k_pp_regs[6]) begin k_pp_regs[6] <= 0; k_pp_active_reg <= 8'h40; end |
else |
if (k_pp_regs[5]) begin k_pp_regs[5] <= 0; k_pp_active_reg <= 8'h20; end |
else |
if (k_pp_regs[4]) begin k_pp_regs[4] <= 0; k_pp_active_reg <= 8'h10; end |
else |
if (k_pp_regs[3]) begin k_pp_regs[3] <= 0; k_pp_active_reg <= 8'h08; end |
else |
if (k_pp_regs[2]) begin k_pp_regs[2] <= 0; k_pp_active_reg <= 8'h04; end |
else |
if (k_pp_regs[1]) begin k_pp_regs[1] <= 0; k_pp_active_reg <= 8'h02; end |
else |
if (k_pp_regs[0]) begin k_pp_regs[0] <= 0; k_pp_active_reg <= 8'h01; end |
end |
`SEQ_PREPULL: |
begin |
k_inc_su <= 1; |
k_mem_dest <= `MEMDEST_MH; |
next_mem_state <= `SEQ_PREPULL; |
if (k_pp_regs[0]) begin k_pp_active_reg <= 8'h01; k_pp_regs[0] <= 0; state <= `SEQ_MEM_READ_L; end |
else |
if (k_pp_regs[1]) begin k_pp_active_reg <= 8'h02; k_pp_regs[1] <= 0; state <= `SEQ_MEM_READ_L; end |
else |
if (k_pp_regs[2]) begin k_pp_active_reg <= 8'h04; k_pp_regs[2] <= 0; state <= `SEQ_MEM_READ_L; end |
else |
if (k_pp_regs[3]) begin k_pp_active_reg <= 8'h08; k_pp_regs[3] <= 0; state <= `SEQ_MEM_READ_L; end |
else |
if (k_pp_regs[4]) begin k_pp_active_reg <= 8'h10; k_pp_regs[4] <= 0; state <= `SEQ_MEM_READ_H;end |
else |
if (k_pp_regs[5]) begin k_pp_active_reg <= 8'h20; k_pp_regs[5] <= 0; state <= `SEQ_MEM_READ_H;end |
else |
if (k_pp_regs[6]) begin k_pp_active_reg <= 8'h40; k_pp_regs[6] <= 0; state <= `SEQ_MEM_READ_H; end |
else |
begin |
next_mem_state <= `SEQ_FETCH; // end of sequence |
if (k_pp_regs[7]) begin k_pp_active_reg <= 8'h80; k_pp_regs[7] <= 0; state <= `SEQ_MEM_READ_H; end |
end |
end |
`SEQ_PUSH_WRITE_L: // first low byte push |
begin |
k_cpu_data_o <= regs_o_left_path_data[7:0]; |
state <= `SEQ_PUSH_WRITE_L_1; |
k_cpu_we <= 1; // write |
k_cpu_addr <= regs_o_su; |
k_dec_su <= 1; // decrement stack pointer |
end |
`SEQ_PUSH_WRITE_L_1: |
begin |
if (k_pp_active_reg[7:4] > 0) |
state <= `SEQ_PUSH_WRITE_H; |
else |
if (k_pp_regs[3:0] > 0) |
state <= `SEQ_PREPUSH; |
else |
state <= next_push_state; |
end |
`SEQ_PUSH_WRITE_H: // reads high byte |
begin |
k_cpu_data_o <= regs_o_left_path_data[15:8]; |
state <= `SEQ_PUSH_WRITE_H_1; |
k_cpu_we <= 1; // write |
k_cpu_addr <= regs_o_su; |
k_dec_su <= 1; // decrement stack pointer |
end |
`SEQ_PUSH_WRITE_H_1: |
begin |
state <= next_state; |
end |
`SEQ_PC_READ_H: // reads high byte for [PC], used by IMM, DIR, EXT |
begin |
k_cpu_addr <= regs_o_pc; |
state <= `SEQ_PC_READ_H_1; |
k_inc_pc <= 1; |
end |
`SEQ_PC_READ_H_1: |
begin |
k_cpu_oe <= 1; // read |
state <= `SEQ_PC_READ_H_2; |
end |
`SEQ_PC_READ_H_2: |
begin |
case (dec_o_p1_mode) |
`REL16, `IMMEDIATE: k_memhi <= cpu_data_i; |
`EXTENDED: k_eahi <= cpu_data_i; |
`INDEXED: k_ofshi <= cpu_data_i; |
endcase |
state <= `SEQ_PC_READ_L; |
end |
`SEQ_PC_READ_L: // reads low byte [PC] |
begin |
k_cpu_addr <= regs_o_pc; |
state <= `SEQ_PC_READ_L_1; |
k_inc_pc <= 1; |
end |
`SEQ_PC_READ_L_1: |
begin |
k_cpu_oe <= 1; // read |
state <= `SEQ_PC_READ_L_2; |
end |
`SEQ_PC_READ_L_2: |
begin |
case (dec_o_p1_mode) |
`NONE: k_pp_regs <= cpu_data_i; // push & pull |
`REL8, `REL16, `IMMEDIATE: k_memlo <= cpu_data_i; |
`DIRECT, `EXTENDED: k_ealo <= cpu_data_i; |
`INDEXED: k_ofslo <= cpu_data_i; |
endcase |
state <= next_state; |
end |
`SEQ_MEM_READ_H: // reads high byte |
begin |
case (dec_o_p1_mode) |
`NONE: begin k_cpu_addr <= regs_o_su; k_inc_su <= 1; end // pull, rts, rti |
`INDEXED: k_cpu_addr <= regs_o_eamem_addr; |
default: k_cpu_addr <= { k_eahi, k_ealo }; |
endcase |
state <= `SEQ_MEM_READ_H_1; |
end |
`SEQ_MEM_READ_H_1: |
begin |
k_cpu_oe <= 1; // read |
state <= `SEQ_MEM_READ_H_2; |
end |
`SEQ_MEM_READ_H_2: |
begin |
case (k_mem_dest) |
`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; |
k_cpu_addr <= k_cpu_addr + 16'h1; |
end |
`SEQ_MEM_READ_L: // reads high byte |
begin |
case (dec_o_p1_mode) |
`NONE: k_cpu_addr <= regs_o_su; // pull, rts, rti |
`INDEXED: k_cpu_addr <= regs_o_eamem_addr; |
default: k_cpu_addr <= { k_eahi, k_ealo }; |
endcase |
state <= `SEQ_MEM_READ_L_1; |
end |
`SEQ_MEM_READ_L_1: |
begin |
k_cpu_oe <= 1; // read |
state <= `SEQ_MEM_READ_L_2; |
end |
`SEQ_MEM_READ_L_2: |
begin |
case (k_mem_dest) |
`MEMDEST_PC: begin k_new_pc[7:0] <= cpu_data_i; k_write_pc <= 1; end |
`MEMDEST_MH: k_memlo <= cpu_data_i; |
`MEMDEST_AH: k_ealo <= cpu_data_i; |
endcase |
case (dec_o_p1_mode) |
`NONE, `INHERENT: k_pull_reg_write <= 1; // pull, rts, rti |
endcase |
state <= next_mem_state; |
end |
`SEQ_MEM_WRITE_H: // writes high byte |
begin |
case (dec_o_p1_mode) |
`INDEXED: k_cpu_addr <= regs_o_eamem_addr; |
default: k_cpu_addr <= { k_eahi, k_ealo }; |
endcase |
k_cpu_data_o <= datamux_o_dest[7:0]; |
state <= `SEQ_MEM_WRITE_H_1; |
k_cpu_we <= 1; // read |
end |
`SEQ_MEM_WRITE_H_1: |
begin |
state <= `SEQ_MEM_WRITE_L; |
k_cpu_addr <= k_cpu_addr + 16'h1; |
end |
`SEQ_MEM_WRITE_L: // reads high byte |
begin |
if (!dec_o_alu_size) |
case (dec_o_p1_mode) |
`INDEXED: k_cpu_addr <= regs_o_eamem_addr; |
default: k_cpu_addr <= { k_eahi, k_ealo }; |
endcase |
k_cpu_data_o <= datamux_o_dest[7:0]; |
state <= `SEQ_MEM_WRITE_L_1; |
k_cpu_we <= 1; // write |
end |
`SEQ_MEM_WRITE_L_1: |
begin |
k_write_post_incdec <= dec_o_ea_wpost; |
state <= next_mem_state; |
end |
|
endcase |
end |
end |
|
initial |
begin |
k_cpu_oe = 0; |
k_cpu_we = 0; |
k_mem_dest = 0; |
k_new_pc = 16'hffff; |
end |
endmodule |
/rtl/verilog/TODO.txt
0,0 → 1,8
Unfinished tasks are described here |
|
28.12.13 |
-------- |
|
- HD6309 compatibility totally missing. Only the ALU paths have been layed out. |
- E flags not taken into account after RTI |
- Z flag for LEAX/LEAY |
/rtl/verilog/defs.v
0,0 → 1,171
|
`default_nettype none |
|
`define RN_ACCD 4'h0 |
`define RN_IX 4'h1 |
`define RN_IY 4'h2 |
`define RN_U 4'h3 |
`define RN_S 4'h4 |
`define RN_PC 4'h5 |
`define RN_MEM16 4'h6 |
`define RN_IMM16 4'h7 |
`define RN_ACCA 4'h8 |
`define RN_ACCB 4'h9 |
`define RN_CC 4'ha |
`define RN_DP 4'hb |
`define RN_MEM8 4'hc |
`define RN_IMM8 4'hd |
`define RN_INV 4'hf |
|
|
// opcodes that need an ALU result |
`define NOP 5'b00000 |
`define CMP 5'b00001 |
`define SBC 5'b00010 |
`define ADD 5'b00011 |
`define AND 5'b00100 |
`define BIT 5'b00101 |
`define LD 5'b00110 |
`define ST 5'b00111 |
`define EOR 5'b01000 |
`define ADC 5'b01001 |
`define OR 5'b01010 |
`define SUB 5'b01011 |
`define T168L 5'b01100 |
`define T168H 5'b01101 |
`define SEXT 5'b01110 |
`define EXG 5'b01111 |
|
`define NEG 5'b10000 |
`define COM 5'b10011 |
`define LSR 5'b10100 |
`define ROR 5'b10110 |
`define ASR 5'b10111 |
`define LSL 5'b11000 |
`define ROL 5'b11001 |
`define ORCC 5'b11010 |
`define ANDCC 5'b11011 |
|
`define DAA 5'b11100 |
`define MUL 5'b11101 |
`define T816 5'b11110 |
|
/* Sequencer states */ |
|
`define SEQ_COLDRESET 'h00 |
`define SEQ_NMI 'h01 |
`define SEQ_SWI 'h02 |
`define SEQ_IRQ 'h03 |
`define SEQ_FIRQ 'h04 |
`define SEQ_SWI2 'h05 |
`define SEQ_SWI3 'h06 |
`define SEQ_UNDEF 'h07 |
`define SEQ_LOADPC 'h08 |
`define SEQ_FETCH 'h09 |
`define SEQ_FETCH_1 'h0a |
`define SEQ_FETCH_2 'h0b |
`define SEQ_FETCH_3 'h0c |
`define SEQ_FETCH_4 'h0d |
`define SEQ_FETCH_5 'h0e |
|
`define SEQ_DECODE 'h0f |
`define SEQ_DECODE_P23 'h10 |
|
`define SEQ_GRAL_ALU 'h11 // x |
`define SEQ_GRAL_WBACK 'h12 // x |
`define SEQ_INH_ALU 'h13 |
`define SEQ_INH_SWI 'h14 |
|
`define SEQ_IND_READ_EA 'h15 // offset 8 or 16 bits |
`define SEQ_IND_READ_EA_1 'h16 |
`define SEQ_IND_READ_EA_2 'h17 // real operand from memory indirect |
`define SEQ_IND_DECODE 'h18 |
`define SEQ_IND_DECODE_OFS 'h19 // used to load 8 or 16 bits offset |
`define SEQ_JMP_LOAD_PC 'h1a |
|
|
`define SEQ_JSR_PUSH 'h1b |
`define SEQ_JSR_PUSH_L 'h1c |
`define SEQ_RTS_POP_L 'h1d |
`define SEQ_RTS_POP_H 'h1e |
|
`define SEQ_PREPUSH 'h20 |
`define SEQ_PREPULL 'h21 |
`define SEQ_PUSH_WRITE_L 'h22 |
`define SEQ_PUSH_WRITE_L_1 'h23 |
`define SEQ_PUSH_WRITE_H 'h24 |
`define SEQ_PUSH_WRITE_H_1 'h25 |
|
`define SEQ_PC_READ_H 'h30 |
`define SEQ_PC_READ_H_1 'h31 |
`define SEQ_PC_READ_H_2 'h32 |
`define SEQ_PC_READ_L 'h33 |
`define SEQ_PC_READ_L_1 'h34 |
`define SEQ_PC_READ_L_2 'h35 |
|
`define SEQ_MEM_READ_H 'h36 |
`define SEQ_MEM_READ_H_1 'h37 |
`define SEQ_MEM_READ_H_2 'h38 |
`define SEQ_MEM_READ_L 'h39 |
`define SEQ_MEM_READ_L_1 'h3a |
`define SEQ_MEM_READ_L_2 'h3b |
`define SEQ_MEM_WRITE_H 'h3c |
`define SEQ_MEM_WRITE_H_1 'h3d |
`define SEQ_MEM_WRITE_L 'h3e |
`define SEQ_MEM_WRITE_L_1 'h3f |
|
|
//`define FLAGC regs_o_CCR[0] |
//`define FLAGV regs_o_CCR[1] |
//`define FLAGZ regs_o_CCR[2] |
//`define FLAGN regs_o_CCR[3] |
`define FLAGI regs_o_CCR[5] |
`define FLAGF regs_o_CCR[6] |
//`define FLAGE regs_o_CCR[7] |
|
`define DFLAGC CCR[0] |
`define DFLAGV CCR[1] |
`define DFLAGZ CCR[2] |
`define DFLAGN CCR[3] |
// some wires exist only for simulation |
`define SIMULATION 1 |
// Adressing modes |
`define NONE 3'h0 |
`define IMMEDIATE 3'h1 |
`define INHERENT 3'h2 |
`define DIRECT 3'h3 |
`define INDEXED 3'h4 |
`define EXTENDED 3'h5 |
`define REL8 3'h6 |
`define REL16 3'h7 |
|
// Address size |
|
// memory transfer size, read or written, used for addresses |
`define MSZ_0 2'h0 |
`define MSZ_8 2'h1 |
`define MSZ_16 2'h2 |
// Data transfer size, to save to register, used for data from memory and to save results to memory/registers |
`define DSZ_0 2'h0 |
`define DSZ_8 2'h1 |
`define DSZ_16 2'h2 |
|
`define OP_NONE 3'h0 |
`define OP_PUSH 3'h1 |
`define OP_PULL 3'h2 |
`define OP_RTS 3'h3 |
`define OP_JSR 3'h4 |
`define OP_ST 3'h5 |
`define OP_LD 3'h6 |
`define OP_LEA 3'h7 |
|
/* alu decoder right path modifier */ |
`define MOD_DEFAULT 2'h0 |
`define MOD_ONE 2'h1 |
`define MOD_ZERO 2'h2 |
`define MOD_MINUS1 2'h3 |
|
`define MEMDEST_PC 2'h0 |
`define MEMDEST_MH 2'h1 |
`define MEMDEST_AH 2'h2 |
`define MEMDEST_I16 2'h3 |
/rtl/verilog/regblock.v
0,0 → 1,224
/* |
* MC6809 Register block, dual ported |
*/ |
`include "defs.v" |
|
|
module regblock( |
input wire clk_in, |
input wire [3:0] path_left_addr, |
input wire [3:0] path_right_addr, |
input wire [3:0] write_reg_addr, |
input wire [7:0] eapostbyte, // effective address post byte |
input wire [15:0] offset16, // up to 16 bit offset for effective address calculation |
input wire write_reg_8, |
input wire write_reg_16, |
input wire write_pull_reg, |
input wire write_post, |
input wire write_pc, |
input wire inc_pc, |
input wire inc_su, /* increments S or U */ |
input wire dec_su, /* decrements s or u */ |
input wire use_s, /* increments S or U */ |
input wire [15:0] data_w, |
input wire [15:0] new_pc, |
input wire [7:0] CCR_in, |
input wire write_flags, |
input wire set_e, |
input wire clear_e, |
output wire [7:0] CCR_o, |
output reg [15:0] path_left_data, |
output reg [15:0] path_right_data, |
output reg [15:0] eamem_addr, |
output wire [15:0] reg_pc, |
output wire [7:0] reg_dp, |
output wire [15:0] reg_su |
); |
|
`define ACCD { ACCA, ACCB } |
reg [15:0] IX; |
reg [15:0] IY; |
reg [15:0] SU; |
reg [15:0] SS; |
reg [15:0] PC; |
|
reg [7:0] ACCA; |
reg [7:0] ACCB; |
reg [7:0] DP; |
`define CCR { eflag, fflag, hflag, intff, nff, zff, vff, cff } |
|
reg eflag, fflag, hflag; |
reg intff, nff, zff, vff, cff; |
reg [15:0] ea_reg, ea_reg_post; |
|
assign CCR_o = `CCR; |
assign reg_pc = PC; |
assign reg_dp = DP; |
assign reg_su = (use_s) ? SS:SU; /* stack pointer */ |
// left path output, always 16 bits |
always @(*) |
begin |
case (path_left_addr) |
`RN_ACCA: path_left_data = { 8'h0, ACCA }; |
`RN_ACCB: path_left_data = { 8'h0, ACCB }; |
`RN_ACCD: path_left_data = `ACCD; |
`RN_IX: path_left_data = IX; |
`RN_IY: path_left_data = IY; |
`RN_U: path_left_data = SU; |
`RN_S: path_left_data = SS; |
`RN_PC: path_left_data = PC; |
`RN_DP: path_left_data = { 8'h0, DP }; |
default: |
path_left_data = 16'hBEEF; |
endcase |
end |
|
// right path output, always 16 bits |
always @(*) |
begin |
case (path_right_addr) |
`RN_ACCA: path_right_data = { 8'h0, ACCA }; |
`RN_ACCB: path_right_data = { 8'h0, ACCB }; |
`RN_ACCD: path_right_data = `ACCD; |
`RN_IX: path_right_data = IX; |
`RN_IY: path_right_data = IY; |
`RN_U: path_right_data = SU; |
`RN_S: path_right_data = SS; |
`RN_DP: path_right_data = { 8'h0, DP }; |
default: |
path_right_data = 16'hBEEF; |
endcase |
end |
|
always @(*) |
begin |
case (eapostbyte[6:5]) |
2'b00: ea_reg = IX; |
2'b01: ea_reg = IY; |
2'b10: ea_reg = SU; |
2'b11: ea_reg = SS; |
endcase |
end |
// pre-decrement/postincrement |
always @(*) |
begin |
ea_reg_post = ea_reg; |
casex (eapostbyte) |
8'b1xxx0000: ea_reg_post = ea_reg + 16'h1; |
8'b1xxx0001: ea_reg_post = ea_reg + 16'h2; |
8'b1xxx0010: ea_reg_post = ea_reg - 16'h1; |
8'b1xxx0011: ea_reg_post = ea_reg - 16'h2; |
//default: ea_reg_post = ea_reg; |
endcase |
end |
|
/* EA calculation |
* postbyte bytes assembler |
* |
* 0RRnnnnn 0 n,R n is 5 bits signed |
* 1RRi0000 0 ,R+ |
* 1RRi0001 0 ,R++ |
* 1RRi0010 0 ,-R |
* 1RRi0011 0 ,--R |
* 1RR00100 0 ,R no offset |
* 1RRi0101 0 B,R |
* 1RRi0110 0 A,R |
* 1RRi1000 1 n,R n is signed 8 bit |
* 1RRi1001 2 n,R n is signed 16 bit |
* 1RRi1011 0 D,R |
* 1xxi1100 1 n,PC n is signed 8 bit postbyte |
* 1xxi1101 2 n,PC n is 16 bit postbytes |
* |
* RR |
* 00 X |
* 01 Y |
* 10 U |
* 11 S |
*/ |
always @(*) |
begin |
eamem_addr = 16'hFEED; // for debug purposes |
casex (eapostbyte) |
8'b0xx0xxxx: // 5 bit signed offset + |
eamem_addr = ea_reg + { 12'h0, eapostbyte[3:0] }; |
8'b0xx1xxxx: // 5 bit signed offset - |
eamem_addr = ea_reg + { 12'hfff, eapostbyte[3:0] }; |
8'b1xx_x_0000, // post increment, increment occurs at a later stage |
8'b1xx_x_0001, // post increment, increment occurs at a later stage |
8'b1xx_x_0100: // no offset |
eamem_addr = ea_reg; |
8'b1xx_x_0010, // pre decrement |
8'b1xx_x_0011: // pre decrement |
eamem_addr = ea_reg_post; // gets precalculated pre-decremented address |
8'b1xx_x_0101: // B,R |
eamem_addr = ea_reg + { {8{ACCB[7]}}, ACCB }; |
8'b1xx_x_0110: // A,R |
eamem_addr = ea_reg + { {8{ACCA[7]}}, ACCA }; |
8'b1xx_x_1011: // D,R |
eamem_addr = ea_reg + `ACCD; |
8'b1xx_x_1000: // n,R 8 bit offset |
eamem_addr = ea_reg + { offset16[7] ? 8'hff:8'h0, offset16[7:0] }; // from postbyte1 |
8'b1xx_x_1001: // n,R // 16 bit offset |
eamem_addr = ea_reg + offset16; |
8'b1xx_x_1100: // n,PC |
eamem_addr = PC + { offset16[7] ? 8'hff:8'h0, offset16[7:0] }; |
8'b1xx_x_1101: // n,PC |
eamem_addr = PC + offset16; |
endcase |
end |
|
always @(posedge clk_in) |
begin |
if (write_reg_8 | write_reg_16 | write_pull_reg) |
case (write_reg_addr) |
0: `ACCD <= data_w; |
1: IX <= data_w; |
2: IY <= data_w; |
3: SU <= data_w; |
4: SS <= data_w; |
5: PC <= data_w; |
8: ACCA <= data_w[7:0]; |
9: ACCB <= data_w[7:0]; |
10: `CCR <= data_w[7:0]; |
11: DP <= data_w[7:0]; |
endcase |
if (write_post) // write back predecrement/postincremented values |
begin |
case (eapostbyte[6:5]) |
2'b00: IX <= ea_reg_post; |
2'b01: IY <= ea_reg_post; |
2'b10: SU <= ea_reg_post; |
2'b11: SS <= ea_reg_post; |
endcase |
end |
if (write_flags) |
begin |
`CCR <= CCR_in; |
end |
if (set_e) |
eflag <= 1; |
if (clear_e) |
eflag <= 0; |
if (write_pc) PC <= new_pc; |
if (inc_pc) PC <= PC + 16'h1; |
if (inc_su) |
if (use_s) SS <= SS + 16'h1; |
else SU <= SU + 16'h1; |
if (dec_su) |
if (use_s) SS <= SS - 16'h1; |
else SU <= SU - 16'h1; |
end |
|
`ifdef SIMULATION |
initial |
begin |
PC = 16'hfffe; |
DP = 8'h00; |
IX = 16'h0; |
`CCR = 0; |
IY = 16'hA55A; |
SS = 16'h0f00; |
SU = 16'h0e00; |
end |
`endif |
endmodule |
/rtl/verilog/decoders.v
0,0 → 1,370
|
/* |
* Signals which registers have to be read/written for the current opcode |
* |
* |
* |
*/ |
`include "defs.v" |
module decode_regs( |
input wire [7:0] opcode, |
input wire [7:0] postbyte0, |
input wire page2_valid, // is 1 when the postbyte0 is a valid opcode (after it was loaded) |
input wire page3_valid, // is 1 when the postbyte0 is a valid opcode (after it was loaded) |
output reg [3:0] path_left_addr, |
output reg [3:0] path_right_addr, |
output reg [3:0] dest_reg, |
output wire write_dest_8, |
output wire write_dest_16, |
output wire result_size |
); |
// for registers, memory writes are handled differently |
assign write_dest_8 = ((dest_reg >= `RN_ACCA) && (dest_reg <= `RN_DP)) ? 1:0; |
assign write_dest_16 = (dest_reg < `RN_IMM16) ? 1:0; |
assign result_size = (dest_reg < `RN_IMM16) ? 1:0; |
always @(opcode, postbyte0, page2_valid, page3_valid) |
begin |
path_left_addr = `RN_INV; |
path_right_addr = `RN_INV; |
dest_reg = `RN_INV; |
|
if (page2_valid | page3_valid) |
begin |
casex(postbyte0) |
8'h83, 8'h93, 8'ha3, 8'hb3: path_left_addr = `RN_ACCD; |
8'h8c, 8'h9c, 8'hac, 8'hbc: path_left_addr = `RN_IY; |
8'h8e, 8'h9e, 8'hae, 8'hbe: path_left_addr = `RN_IY; |
8'h8f, 8'h9f, 8'haf, 8'hbf: path_left_addr = `RN_IY; |
endcase |
casex (postbyte0) // right arm |
8'h83, 8'h8c, 8'h8e, 8'h8f: path_right_addr = `RN_IMM16; |
8'h93, 8'ha3, 8'hb3: path_right_addr = `RN_MEM16; |
8'h9c, 8'hac, 8'hbc: path_right_addr = `RN_MEM16; |
8'h9e, 8'hae, 8'hbe: path_right_addr = `RN_MEM16; |
8'h9f, 8'haf, 8'hbf: path_right_addr = `RN_MEM16; |
endcase |
casex(postbyte0) // dest |
8'h83, 8'h93, 8'ha3, 8'hb3: begin end // only flags |
8'h8c, 8'h9c, 8'hac, 8'hbc: begin end // only flags |
8'h8e, 8'h9e, 8'hae, 8'hbe: dest_reg = `RN_IY; |
8'h8f, 8'h9f, 8'haf, 8'hbf: dest_reg = `RN_MEM16; |
endcase |
end |
// destination |
casex(opcode) |
8'h30: dest_reg = `RN_IX; |
8'h31: dest_reg = `RN_IY; |
8'h32: dest_reg = `RN_S; |
8'h33: dest_reg = `RN_U; |
8'h39: dest_reg = `RN_PC; // rts |
8'h3d: begin path_left_addr = `RN_ACCA; path_right_addr = `RN_ACCB; dest_reg = `RN_ACCD; end // mul |
8'h4x: begin path_left_addr = `RN_ACCA; dest_reg = `RN_ACCA; end |
8'h5x: begin path_left_addr = `RN_ACCB; dest_reg = `RN_ACCB; end |
8'h0x, 8'h7x: begin path_left_addr = `RN_MEM8; dest_reg = `RN_MEM8; end |
8'h6x: |
case (opcode[3:0]) |
4'hf: begin dest_reg = `RN_MEM8; end // CLR, only dest |
default: begin path_left_addr = `RN_MEM8; dest_reg = `RN_MEM8; end |
endcase |
8'h4x, 8'h8x, 8'h9x, 8'hax, 8'hbx: |
case (opcode[3:0]) |
4'h3: begin path_left_addr = `RN_ACCD; dest_reg = `RN_ACCD; end |
4'h7: begin path_left_addr = `RN_ACCA; dest_reg = `RN_MEM8; end |
4'hc, 4'he, 4'hf: begin path_left_addr = `RN_IX; dest_reg = `RN_IX; end |
4'hd: begin end // nothing active, jsr |
default: begin path_left_addr = `RN_ACCA; dest_reg = `RN_ACCA; end |
endcase |
8'h5x, 8'hcx, 8'hdx, 8'hex, 8'hfx: |
case (opcode[3:0]) |
4'h3, 4'hc: begin path_left_addr = `RN_ACCD; dest_reg = `RN_ACCD; end |
4'h7: begin path_left_addr = `RN_ACCB; dest_reg = `RN_MEM8; end // store to mem |
4'he: begin path_left_addr = `RN_U; dest_reg = `RN_IX; end |
4'hf: begin path_left_addr = `RN_IX; dest_reg = `RN_IX; end |
4'hd: begin path_left_addr = `RN_ACCD; end |
default: begin path_left_addr = `RN_ACCB; dest_reg = `RN_ACCB; end |
endcase |
endcase |
casex (opcode) // right arm |
// 8x and Cx |
8'b1x00_000x, 8'b1x00_0010: path_right_addr = `RN_IMM8; |
8'b1x00_0011, 8'b1x00_11x0, 8'b1x00_1111: path_right_addr = `RN_IMM16; |
8'b1x00_010x, 8'b1x00_0110, |
8'b1x00_10xx: path_right_addr = `RN_IMM8; |
// 9, A, B, D, E, F |
8'b1x01_000x, 8'b1x01_0010: path_right_addr = `RN_MEM8; |
8'b1x01_0011, 8'b1x01_11x0, 8'b1x01_1111: path_right_addr = `RN_MEM16; |
8'b1x01_010x, 8'b1x01_0110, |
8'b1x01_10xx: path_right_addr = `RN_MEM8; |
8'b1x1x_000x, 8'b1x1x_0010: path_right_addr = `RN_MEM8; |
8'b1x1x_0011, 8'b1x1x_11x0, 8'b1x1x_1111: path_right_addr = `RN_MEM16; |
8'b1x1x_010x, 8'b1x1x_0110, |
8'b1x1x_10xx: path_right_addr = `RN_MEM8; |
endcase |
end |
|
endmodule |
|
/* Decodes module and addressing mode for page 1 opcodes */ |
module decode_op( |
input wire [7:0] opcode, |
input wire [7:0] postbyte0, |
input wire page2_valid, // is 1 when the postbyte0 is a valid opcode (after it was loaded) |
input wire page3_valid, // is 1 when the postbyte0 is a valid opcode (after it was loaded) |
output reg [2:0] mode, |
output reg [2:0] optype, |
output reg use_s |
); |
|
wire [3:0] oplo; |
reg size; |
assign oplo = opcode[3:0]; |
|
always @(opcode, postbyte0, page2_valid, page3_valid, oplo) |
begin |
//dsize = `DSZ_8; // data operand size |
//msize = `MSZ_8; // memory operand size |
optype = `OP_NONE; |
use_s = 1; |
mode = `NONE; |
size = 0; |
// Addressing mode |
casex(opcode) |
8'h0x: begin mode = `DIRECT; end |
8'h12, 8'h13, 8'h19: mode = `INHERENT; |
8'h14, 8'h15, 8'h18, 8'h1b: mode = `NONE; // undefined opcodes |
8'h16: mode = `REL16; |
8'h17: begin mode = `REL16; optype = `OP_JSR; end |
8'h1a, 8'h1c, 8'h1d, 8'h1e, 8'h1f: mode = `IMMEDIATE; // handled in ALU ORCC, ANDCC, SEX, EXG, TFR |
|
8'h2x: mode = `REL8; |
8'h30, 8'h31, 8'h32, 8'h33: begin mode = `INDEXED; optype = `OP_LEA; end |
8'h34: begin optype = `OP_PUSH; mode = `NONE; end |
8'h35: begin optype = `OP_PULL; mode = `NONE; end |
8'h36: begin optype = `OP_PUSH; mode = `NONE; use_s = 0; end |
8'h37: begin optype = `OP_PULL; mode = `NONE; use_s = 0; end |
8'h38, 8'h3e: mode = `NONE; |
// don't change to inh because SEQ_MEM_READ_x would not use register S as address |
8'h39, 8'h3b: begin mode = `NONE; optype = `OP_RTS; end |
8'h3a, 8'h3c, 8'h3d, 8'h3f: mode = `INHERENT; |
|
8'h4x: begin mode = `INHERENT; end |
8'h5x: begin mode = `INHERENT; end |
8'h6x: begin mode = `INDEXED; end |
8'h7x: begin mode = `EXTENDED; end |
8'h8x: |
begin |
case (oplo) |
4'h3, 4'hc, 4'he: begin mode = `IMMEDIATE; size = 1; end |
4'hd: mode = `REL8; // bsr |
default: mode = `IMMEDIATE; |
endcase |
end |
8'hcx: |
begin |
case (oplo) |
4'h3, 4'hc, 4'he: begin mode = `IMMEDIATE; size = 1; end |
default: mode = `IMMEDIATE; |
endcase |
end |
8'h9x, 8'hdx: begin mode = `DIRECT; end |
8'hax, 8'hex: begin mode = `INDEXED; end |
8'hbx, 8'hfx: begin mode = `EXTENDED; end |
endcase |
// Opcode type |
casex(opcode) |
8'b1xxx0110: optype = `OP_LD; |
8'b1xxx0111: optype = `OP_ST; |
8'b11xx1100: optype = `OP_LD; // LDD |
8'b10xx1101: begin optype = `OP_JSR; end// bsr & jsr |
8'b1xxx1110: optype = `OP_LD; // LDX, LDU |
8'b1xxx1111, 8'b1xxx1101: optype = `OP_ST; |
endcase |
if (page2_valid == 1'b1) |
begin |
casex(postbyte0) |
8'h1x: mode = `REL16; |
8'h2f: mode = `INHERENT; |
8'h83: begin mode = `IMMEDIATE; size = 1; end |
//8'h93, 8'ha3, 8'hb3: begin mem16 = 1; size = 1; end |
8'h8c: begin mode = `IMMEDIATE; size = 1; end |
//8'h9c, 8'hac, 8'hbc: begin mem16 = 1; size = 1; end |
8'h8e: begin mode = `IMMEDIATE; size = 1; end |
//8'h9e, 8'hae, 8'hbe: begin mem16 = 1; size = 1; end |
//8'h9f, 8'haf, 8'hbf: begin mem16 = 1; size = 1; end |
8'hce: begin mode = `IMMEDIATE; size = 1; end |
//8'hde, 8'hee, 8'hfe: begin mem16 = 1; size = 1; end |
//8'hdf, 8'hef, 8'hff: begin mem16 = 1; size = 1; end |
endcase |
casex( postbyte0) |
8'h9x, 8'hdx: mode = `DIRECT; |
8'hax, 8'hex: mode = `INDEXED; |
8'hbx, 8'hfx: mode = `EXTENDED; |
endcase |
casex( postbyte0) |
8'b1xxx1110: optype = `OP_LD; // LDY, LDS |
8'b1xxx1111, 8'b1xxx1101: optype = `OP_ST; // STY, STS |
endcase |
end |
if (page3_valid == 1'b1) |
begin |
casex(postbyte0) |
8'h2f: mode = `INHERENT; |
8'h83: begin mode = `IMMEDIATE; size = 1; end // CMPD |
//8'h93, 8'ha3, 8'hb3: begin mem16 = 1; size = 1; end // CMPD |
8'h8c: begin mode = `IMMEDIATE; size = 1; end |
//8'h9c, 8'hac, 8'hbc: begin mem16 = 1; size = 1; end |
8'h8e: begin mode = `IMMEDIATE; size = 1; end |
//8'h9e, 8'hae, 8'hbe: begin mem16 = 1; size = 1; end |
//8'h9f, 8'haf, 8'hbf: begin mem16 = 1; size = 1; end |
8'hce: begin mode = `IMMEDIATE; size = 1; end |
//8'hde, 8'hee, 8'hfe: begin mem16 = 1; size = 1; end |
//8'hdf, 8'hef, 8'hff: begin mem16 = 1; size = 1; end |
endcase |
casex( postbyte0) |
8'h9x, 8'hdx: mode = `DIRECT; |
8'hax, 8'hex: mode = `INDEXED; |
8'hbx, 8'hfx: mode = `EXTENDED; |
endcase |
end |
end |
|
endmodule |
|
/* Decodes the Effective Address postbyte |
to recover size of offset to load and post-incr/pre-decr info |
*/ |
module decode_ea( |
input wire [7:0] eapostbyte, |
output reg noofs, |
output reg ofs8, // needs an 8 bit offset |
output reg ofs16, // needs an 16 bit offset |
output reg write_post, // needs to write back a predecr or post incr |
output wire isind // signals when the mode is indirect, the memory at the address is read to load the real address |
); |
|
assign isind = (eapostbyte[7] & eapostbyte[4]) ? 1'b1:1'b0; |
always @(*) |
begin |
noofs = 0; |
ofs8 = 0; |
ofs16 = 0; |
write_post = 0; |
casex (eapostbyte) |
8'b0xxxxxxx, 8'b1xx00100: noofs = 1; |
8'b1xxx1000, 8'b1xxx1100: ofs8 = 1; |
8'b1xxx1001, 8'b1xxx1101: ofs16 = 1; |
8'b1xx11111: ofs16 = 1; // extended indirect |
8'b1xxx00xx: write_post = 1; |
endcase |
end |
endmodule |
|
module decode_alu( |
input wire [7:0] opcode, |
input wire [7:0] postbyte0, |
input wire page2_valid, // is 1 when the postbyte0 was loaded and is page2 opcode |
input wire page3_valid, // is 1 when the postbyte0 was loaded and is page3 opcode |
output reg [4:0] alu_opcode, |
output reg [1:0] dec_alu_right_path_mod, |
output wire dest_flags |
); |
|
assign dest_flags = alu_opcode != `NOP; |
always @(*) |
begin |
alu_opcode = `NOP; |
dec_alu_right_path_mod = `MOD_DEFAULT; |
casex (opcode) |
8'b1xxx_0000: alu_opcode = `SUB; |
8'b1xxx_0001: alu_opcode = `CMP; |
8'b1xxx_0010: alu_opcode = `SBC; |
8'b10xx_0011: alu_opcode = `SUB; |
8'b11xx_0011: alu_opcode = `ADD; |
8'b1xxx_0100: alu_opcode = `AND; |
8'b1xxx_0101: alu_opcode = `BIT; |
8'b1xxx_0110: alu_opcode = `LD; |
8'b1xxx_0111: alu_opcode = `ST; |
8'b1xxx_1000: alu_opcode = `EOR; |
8'b1xxx_1001: alu_opcode = `ADC; |
8'b1xxx_1010: alu_opcode = `OR; |
8'b1xxx_1011: alu_opcode = `ADD; |
8'b10xx_1100: alu_opcode = `CMP; |
8'b11xx_1100: alu_opcode = `LD; |
8'b11xx_1101: alu_opcode = `LD; |
8'b1xxx_1110: alu_opcode = `LD; |
8'b1xxx_1111: alu_opcode = `ST; |
|
8'h00, 8'b01xx_0000: alu_opcode = `NEG; |
8'h03, 8'b01xx_0011: alu_opcode = `COM; |
8'h04, 8'b01xx_0100: alu_opcode = `LSR; |
8'h06, 8'b01xx_0110: alu_opcode = `ROR; |
8'h07, 8'b01xx_0111: alu_opcode = `ASR; |
8'h08, 8'b01xx_1000: alu_opcode = `LSL; |
8'h09, 8'b01xx_1001: alu_opcode = `ROL; |
8'h0a, 8'b01xx_1010: begin alu_opcode = `SUB; dec_alu_right_path_mod = `MOD_MINUS1; end // dec |
8'h0c, 8'b01xx_1100: begin alu_opcode = `ADD; dec_alu_right_path_mod = `MOD_ONE; end // inc |
8'h0d, 8'b01xx_1101: alu_opcode = `AND; |
8'h0f, 8'b01xx_1111: begin alu_opcode = `LD; dec_alu_right_path_mod = `MOD_ZERO; end // CLR |
|
8'h19: alu_opcode = `DAA; |
8'h1a: alu_opcode = `ORCC; |
8'h1c: alu_opcode = `ANDCC; |
8'h1d: alu_opcode = `SEXT; |
8'h1e: alu_opcode = `EXG; |
8'h3d: alu_opcode = `MUL; |
endcase |
if (page2_valid) |
casex (postbyte0) |
8'b10xx_0011, |
8'b10xx_1010: alu_opcode = `CMP; |
8'b1xxx_1110: alu_opcode = `LD; |
8'b1xxx_1111: alu_opcode = `ST; |
endcase |
if (page3_valid) |
casex (postbyte0) |
8'b10xx_0011, |
8'b10xx_1010: alu_opcode = `CMP; |
8'b1xxx_1110: alu_opcode = `LD; |
8'b1xxx_1111: alu_opcode = `ST; |
endcase |
end |
|
endmodule |
/* decodes the condition and checks the flags to see if it is met */ |
module test_condition( |
input wire [7:0] opcode, |
input wire [7:0] postbyte0, |
input wire page2_valid, |
input wire [7:0] CCR, |
output reg cond_taken |
); |
|
wire [7:0] op = page2_valid ? postbyte0:opcode; |
|
always @(*) |
begin |
cond_taken = 1'b0; |
if ((op == 8'h16) || (op == 8'h17) || (op == 8'h8D)) |
cond_taken = 1'b1; // LBRA/LBSR, BSR |
if (op[7:4] == 4'h2) |
case (op[3:0]) |
4'h0: cond_taken = 1'b1; // BRA |
4'h1: cond_taken = 0; // BRN |
4'h2: cond_taken = !(`DFLAGC & `DFLAGZ); // BHI |
4'h3: cond_taken = `DFLAGC | `DFLAGZ; // BLS |
4'h4: cond_taken = !`DFLAGC; // BCC, BHS |
4'h5: cond_taken = `DFLAGC; // BCS, BLO |
4'h6: cond_taken = !`DFLAGZ; // BNE |
4'h7: cond_taken = `DFLAGZ; // BEQ |
4'h8: cond_taken = !`DFLAGV; // BVC |
4'h9: cond_taken = `DFLAGV; // BVS |
4'ha: cond_taken = !`DFLAGN; // BPL |
4'hb: cond_taken = `DFLAGN; // BMI |
4'hc: cond_taken = `DFLAGN == `DFLAGV; // BGE |
4'hd: cond_taken = `DFLAGN != `DFLAGV; // BLT |
4'he: cond_taken = (`DFLAGN == `DFLAGV) & (!`DFLAGZ); // BGT |
4'hf: cond_taken = (`DFLAGN != `DFLAGV) | (`DFLAGZ); // BLE |
endcase |
end |
|
endmodule |
/rtl/verilog/alu16.v
0,0 → 1,519
/* |
* (c) 2013 Alejandro Paz |
* |
* |
* An alu core |
* |
* ADD, ADC, DAA, SUB, SBC, COM, NEG, CMP, ASR, ASL, ROR, ROL, RCR, RCL |
* |
* |
* |
*/ |
`include "defs.v" |
module alu16( |
input wire clk, |
input wire [15:0] a_in, |
input wire [15:0] b_in, |
input wire [7:0] CCR, /* condition code register */ |
input wire [4:0] opcode_in, /* ALU opcode */ |
input wire sz_in, /* size, low 8 bit, high 16 bit */ |
output reg [15:0] q_out, /* ALU result */ |
output reg [7:0] CCRo |
); |
|
wire c_in, n_in, v_in, z_in, h_in; |
assign c_in = CCR[0]; /* carry flag */ |
assign n_in = CCR[3]; /* neg flag */ |
assign v_in = CCR[1]; /* overflow flag */ |
assign z_in = CCR[2]; /* zero flag */ |
assign h_in = CCR[5]; /* halb-carry flag */ |
|
|
wire [7:0] add8_r, adc8_r, sub8_r, sbc8_r, com8_r, neg8_r; |
wire [7:0] asr8_r, shr8_r, shl8_r, ror8_r, rol8_r, and8_r, or8_r, eor8_r; |
wire [15:0] add16_r, adc16_r, sub16_r, sbc16_r, com16_r, neg16_r; |
wire [15:0] asr16_r, shr16_r, shl16_r, ror16_r, rol16_r, and16_r, or16_r, eor16_r, mul16_r; |
wire [3:0] daa8l_r, daa8h_r; |
wire daa_lnm9; |
|
wire [7:0] add8_w, adc8_w, com8_w, neg8_w, sub8_w, sbc8_w; |
wire [7:0] asr8_w, shr8_w, shl8_w, ror8_w, rol8_w, and8_w, or8_w, eor8_w; |
wire [15:0] add16_w, adc16_w, com16_w, neg16_w, sub16_w, sbc16_w; |
wire [15:0] asr16_w, shr16_w, shl16_w, ror16_w, rol16_w, and16_w, or16_w, eor16_w, mul16_w; |
|
wire cadd8_w, cadc8_w, csub8_w, csbc8_w; |
wire cadd16_w, cadc16_w, csub16_w, csbc16_w; |
|
wire cadd8_r, cadc8_r, csub8_r, csbc8_r, ccom8_r, cneg8_r; |
wire casr8_r, cshr8_r, cshl8_r, cror8_r, crol8_r, cand8_r, cdaa8_r; |
wire cadd16_r, cadc16_r, csub16_r, csbc16_r, ccom16_r, cneg16_r; |
wire casr16_r, cshr16_r, cshl16_r, cror16_r, crol16_r, cand16_r, cmul16_r; |
wire vadd8_r, vadc8_r, vsub8_r, vsbc8_r, vcom8_r, vneg8_r; |
wire vasr8_r, vshr8_r, vshl8_r, vror8_r, vrol8_r, vand8_r; |
wire vadd16_r, vadc16_r, vsub16_r, vsbc16_r, vcom16_r, vneg16_r; |
wire vasr16_r, vshr16_r, vshl16_r, vror16_r, vrol16_r, vand16_r; |
|
assign { cadd8_w, add8_w } = { 1'b0, a_in[7:0] } + { 1'b0, b_in[7:0] }; |
assign { cadd16_w, add16_w } = { 1'b0, a_in[15:0] } + { 1'b0, b_in[15:0] }; |
assign { cadc8_w, adc8_w } = { 1'b0, a_in[7:0] } + { 1'b0, b_in[7:0] } + { 8'h0, c_in }; |
assign { cadc16_w, adc16_w } = { 1'b0, a_in[15:0] } + { 1'b0, b_in[15:0] } + { 16'h0, c_in }; |
|
assign { csub8_w, sub8_w } = { 1'b0, a_in[7:0] } - { 1'b0, b_in[7:0] }; |
assign { csub16_w, sub16_w } = { 1'b0, a_in[15:0] } - { 1'b0, b_in[15:0] }; |
assign { csbc8_w, sbc8_w } = { 1'b0, a_in[7:0] } - { 1'b0, b_in[7:0] } - { 8'h0, c_in }; |
assign { csbc16_w, sbc16_w } = { 1'b0, a_in[15:0] } - { 1'b0, b_in[15:0] } - { 16'h0, c_in }; |
|
assign com8_w = ~a_in[7:0]; |
assign com16_w = ~a_in[15:0]; |
assign neg8_w = 8'h0 - a_in[7:0]; |
assign neg16_w = 16'h0 - a_in[15:0]; |
|
assign asr8_w = { a_in[7], a_in[7:1] }; |
assign asr16_w = { a_in[15], a_in[15:1] }; |
|
assign shr8_w = { 1'b0, a_in[7:1] }; |
assign shr16_w = { 1'b0, a_in[15:1] }; |
|
assign shl8_w = { a_in[6:0], 1'b0 }; |
assign shl16_w = { a_in[14:0], 1'b0 }; |
|
assign ror8_w = { c_in, a_in[7:1] }; |
assign ror16_w = { c_in, a_in[15:1] }; |
|
assign rol8_w = { a_in[6:0], c_in }; |
assign rol16_w = { a_in[14:0], c_in }; |
|
assign and8_w = a_in[7:0] & b_in[7:0]; |
assign and16_w = a_in[15:0] & b_in[15:0]; |
|
assign or8_w = a_in[7:0] | b_in[7:0]; |
assign or16_w = a_in[15:0] | b_in[15:0]; |
|
assign eor8_w = a_in[7:0] ^ b_in[7:0]; |
assign eor16_w = a_in[15:0] ^ b_in[15:0]; |
assign mul16_w = a_in[7:0] * b_in[7:0]; |
|
// ADD, ADC |
assign { cadd8_r, add8_r } = { cadd8_w, add8_w }; |
assign vadd8_r = (a_in[7] & b_in[7] & (~add8_w[7])) | ((~a_in[7]) & (~b_in[7]) & add8_w[7]); |
assign { cadd16_r, add16_r } = { cadd16_w, add16_w }; |
assign vadd16_r = (a_in[15] & b_in[15] & (~add16_w[15])) | ((~a_in[15]) & (~b_in[15]) & add16_w[15]); |
assign { cadc8_r, adc8_r } = { cadd8_w, add8_w }; |
assign vadc8_r = (a_in[7] & b_in[7] & (~add8_w[7])) | ((~a_in[7]) & (~b_in[7]) & adc8_w[7]); |
assign { cadc16_r, adc16_r } = { cadd16_w, add16_w }; |
assign vadc16_r = (a_in[15] & b_in[15] & (~add16_w[15])) | ((~a_in[15]) & (~b_in[15]) & adc16_w[15]); |
// SUB, SUBC |
assign { csub8_r, sub8_r } = { csub8_w, sub8_w }; |
assign vsub8_r = (a_in[7] & (~b_in[7]) & (~sub8_w[7])) | ((~a_in[7]) & b_in[7] & sub8_w[7]); |
assign { csub16_r, sub16_r } = { csub16_w, sub16_w }; |
assign vsub16_r = (a_in[15] & b_in[15] & (~add16_w[15])) | ((~a_in[15]) & b_in[15] & sub16_w[15]); |
assign { csbc8_r, sbc8_r } = { csbc8_w, sbc8_w }; |
assign vsbc8_r = (a_in[7] & b_in[7] | (~sbc8_w[7])) | ((~a_in[7]) & b_in[7] & sbc8_w[7]); |
assign { csbc16_r, sbc16_r } = { csbc16_w, sbc16_w }; |
assign vsbc16_r = (a_in[15] & b_in[15] & (~sbc16_w[15])) | ((~a_in[15]) & b_in[15] & sbc16_w[15]); |
// COM |
assign com8_r = com8_w; |
assign ccom8_r = com8_w != 8'h0 ? 1'b1:1'b0; |
assign vcom8_r = 1'b0; |
assign com16_r = com16_w; |
assign ccom16_r = com16_w != 16'h0 ? 1'b1:1'b0; |
assign vcom16_r = 1'b0; |
// NEG |
assign neg8_r = neg8_w; |
assign cneg8_r = neg8_w[7] | neg8_w[6] | neg8_w[5] | neg8_w[4] | neg8_w[3] | neg8_w[2] | neg8_w[1] | neg8_w[0]; |
assign vneg8_r = neg8_w[7] & (~neg8_w[6]) & (~neg8_w[5]) & (~neg8_w[4]) & (~neg8_w[3]) & (~neg8_w[2]) & (~neg8_w[1]) & (~neg8_w[0]); |
assign neg16_r = neg16_w; |
assign vneg16_r = neg16_w[15] & (~neg16_w[14]) & (~neg16_w[13]) & (~neg16_w[12]) & (~neg16_w[11]) & (~neg16_w[10]) & (~neg16_w[9]) & (~neg16_w[8]) & (~neg16_w[7]) & (~neg16_w[6]) & (~neg16_w[5]) & (~neg16_w[4]) & (~neg16_w[3]) & (~neg16_w[2]) & (~neg16_w[1]) & (~neg16_w[0]); |
assign cneg16_r = neg16_w[15] | neg16_w[14] | neg16_w[13] | neg16_w[12] | neg16_w[11] | neg16_w[10] | neg16_w[9] & neg16_w[8] | neg16_w[7] | neg16_w[6] | neg16_w[5] | neg16_w[4] | neg16_w[3] | neg16_w[2] | neg16_w[1] | neg16_w[0]; |
// ASR |
assign asr8_r = asr8_w; |
assign casr8_r = a_in[0]; |
assign vasr8_r = a_in[0] ^ asr8_w[7]; |
assign asr16_r = asr16_w; |
assign casr16_r = a_in[0]; |
assign vasr16_r = a_in[0] ^ asr16_w[15]; |
// SHR |
assign shr8_r = shr8_w; |
assign cshr8_r = a_in[0]; |
assign vshr8_r = a_in[0] ^ shr8_w[7]; |
assign shr16_r = shr16_w; |
assign cshr16_r = a_in[0]; |
assign vshr16_r = a_in[0] ^ shr16_w[15]; |
// SHL |
assign shl8_r = shl8_w; |
assign cshl8_r = a_in[7]; |
assign vshl8_r = a_in[7] ^ shl8_w[7]; |
assign shl16_r = shl16_w; |
assign cshl16_r = a_in[15]; |
assign vshl16_r = a_in[15] ^ shl16_w[15]; |
// ROR |
assign ror8_r = ror8_w; |
assign cror8_r = a_in[0]; |
assign vror8_r = a_in[0] ^ shr8_w[7]; |
assign ror16_r = ror16_w; |
assign cror16_r = a_in[0]; |
assign vror16_r = a_in[0] ^ ror16_w[15]; |
// ROL |
assign rol8_r = shl8_w; |
assign crol8_r = a_in[7]; |
assign vrol8_r = a_in[7] ^ rol8_w[7]; |
assign rol16_r = rol16_w; |
assign crol16_r = a_in[15]; |
assign vrol16_r = a_in[15] ^ rol16_w[15]; |
// AND |
assign and8_r = and8_w; |
assign cand8_r = c_in; |
assign vand8_r = 1'b0; |
assign and16_r = and16_w; |
assign cand16_r = c_in; |
assign vand16_r = 1'b0; |
// OR |
assign or8_r = or8_w; |
assign or16_r = or16_w; |
// EOR |
assign eor8_r = eor8_w; |
assign eor16_r = eor16_w; |
// MUL |
assign mul16_r = mul16_w; |
assign cmul16_r = mul16_w[7]; |
// DAA |
assign daa_lnm9 = (a_in[3:0] > 9); |
assign daa8l_r = (daa_lnm9 | h_in ) ? a_in[3:0] + 4'h6:a_in[3:0]; |
assign daa8h_r = ((a_in[7:4] > 9) || (c_in == 1'b1) || (a_in[7] & daa_lnm9)) ? a_in[7:4] + 4'h6:a_in[7:4]; |
assign cdaa8_r = daa8h_r < a_in[7:4]; |
|
reg c8, h8, n8, v8, z8, c16, n16, v16, z16; |
reg [7:0] q8; |
reg [15:0] q16; |
|
always @(*) |
begin |
q8 = 8'h0; |
q16 = 16'h0; |
c8 = c_in; |
h8 = h_in; |
v8 = v_in; |
c16 = c_in; |
v16 = v_in; |
case (opcode_in) |
`ADD: |
begin |
q8 = add8_r; |
c8 = cadd8_r; |
v8 = vadd8_r; |
q16 = add16_r; |
c16 = cadd16_r; |
v16 = vadd16_r; |
end |
`ADC: |
begin |
q8 = adc8_r; |
c8 = cadc8_r; |
v8 = vadc8_r; |
q16 = adc16_r; |
c16 = cadc16_r; |
v16 = vadc16_r; |
end |
`CMP, `SUB: // for CMP no register result is written back |
begin |
q8 = sub8_r; |
c8 = csub8_r; |
v8 = vsub8_r; |
q16 = sub16_r; |
c16 = csub16_r; |
v16 = vsub16_r; |
end |
`SBC: |
begin |
q8 = sbc8_r; |
c8 = csbc8_r; |
v8 = vsbc8_r; |
q16 = sbc16_r; |
c16 = csbc16_r; |
v16 = vsbc16_r; |
end |
`COM: |
begin |
q8 = com8_r; |
c8 = com8_r; |
v8 = vcom8_r; |
q16 = com16_r; |
c16 = ccom16_r; |
v16 = vcom16_r; |
end |
`NEG: |
begin |
q8 = neg8_r; |
c8 = cneg8_r; |
v8 = vneg8_r; |
q16 = neg16_r; |
c16 = cneg16_r; |
v16 = vneg16_r; |
end |
`ASR: |
begin |
q8 = asr8_r; |
c8 = casr8_r; |
v8 = vasr8_r; |
q16 = asr16_r; |
c16 = casr16_r; |
v16 = vasr16_r; |
end |
`LSR: |
begin |
q8 = shr8_r; |
c8 = cshr8_r; |
v8 = vshr8_r; |
q16 = shr16_r; |
c16 = cshr16_r; |
v16 = vshr16_r; |
end |
`LSL: |
begin |
q8 = shl8_r; |
c8 = cshl8_r; |
v8 = vshl8_r; |
q16 = shl16_r; |
c16 = cshl16_r; |
v16 = vshl16_r; |
end |
`ROR: |
begin |
q8 = ror8_r; |
c8 = cror8_r; |
v8 = vror8_r; |
q16 = ror16_r; |
c16 = cror16_r; |
v16 = vror16_r; |
end |
`ROL: |
begin |
q8 = rol8_r; |
c8 = crol8_r; |
v8 = vrol8_r; |
q16 = rol16_r; |
c16 = crol16_r; |
v16 = vrol16_r; |
end |
`AND: |
begin |
q8 = and8_r; |
c8 = cand8_r; |
v8 = vand8_r; |
`ifdef HD6309 |
q16 = and16_r; |
c16 = cand16_r; |
v16 = vand16_r; |
`endif |
end |
`OR: |
begin |
q8 = or8_r; |
c8 = cand8_r; |
v8 = vand8_r; |
`ifdef HD6309 |
q16 = or16_r; |
c16 = cand16_r; |
v16 = vand16_r; |
`endif |
end |
`EOR: |
begin |
q8 = eor8_r; |
c8 = cand8_r; |
v8 = vand8_r; |
`ifdef HD6309 |
q16 = eor16_r; |
c16 = cand16_r; |
v16 = vand16_r; |
`endif |
end |
`DAA: |
begin // V is undefined, so we don't touch it |
q8 = { daa8h_r, daa8l_r }; |
c8 = cdaa8_r; |
end |
`MUL: |
begin |
q16 = mul16_r; |
c16 = cmul16_r; |
end |
`LD: |
begin |
v8 = 0; |
v16 = 0; |
q8 = b_in[7:0]; |
q16 = b_in[15:0]; |
end |
`ST: |
begin |
q8 = a_in[7:0]; |
q16 = a_in[15:0]; |
end |
`T816: // zero extend 8 -> 16 |
begin |
q16 = { 8'h0, b_in[7:0] }; |
end |
`T168L: // 16L -> 8 |
begin |
q8 = b_in[7:0]; |
end |
`T168H: // 16L -> 8 |
begin |
q8 = b_in[15:8]; |
end |
`SEXT: // sign extend |
begin |
q16 = { b_in[7] ? 8'hff:8'h00, b_in[7:0] }; |
end |
endcase |
end |
|
reg [7:0] regq8; |
reg [15:0] regq16; |
reg reg_n_in, reg_z_in; |
/* register before second mux */ |
always @(posedge clk) |
begin |
regq8 <= q8; |
regq16 <= q16; |
reg_n_in <= n_in; |
reg_z_in <= z_in; |
end |
|
/* Negative & zero flags */ |
always @(*) |
begin |
n8 = regq8[7]; |
z8 = regq8 == 8'h0; |
n16 = regq16[15]; |
z16 = regq16 == 16'h0; |
case (opcode_in) |
`ADD: |
begin |
end |
`ADC: |
begin |
end |
`CMP, `SUB: // for CMP no register result is written back |
begin |
end |
`SBC: |
begin |
end |
`COM: |
begin |
end |
`NEG: |
begin |
end |
`ASR: |
begin |
end |
`LSR: |
begin |
end |
`LSL: |
begin |
end |
`ROR: |
begin |
end |
`ROL: |
begin |
end |
`AND: |
begin |
end |
`OR: |
begin |
end |
`EOR: |
begin |
end |
`DAA: |
begin // V is undefined, so we don't touch it |
end |
`MUL: |
begin |
n16 = reg_n_in; |
z16 = reg_z_in; |
end |
`LD: |
begin |
end |
`ST: |
begin |
end |
`T816: // zero extend 8 -> 16 |
begin |
n16 = reg_n_in; |
z16 = reg_z_in; |
end |
`T168L: // 16L -> 8 |
begin |
n8 = reg_n_in; |
z8 = reg_z_in; |
end |
`T168H: // 16L -> 8 |
begin |
n8 = reg_n_in; |
z8 = reg_z_in; |
end |
`SEXT: // sign extend |
begin |
n16 = reg_n_in; |
z16 = reg_z_in; |
end |
endcase |
end |
|
|
always @(*) |
begin |
q_out[15:8] = regq16[15:8]; |
if (sz_in) |
q_out[7:0] = regq16[7:0]; |
else |
q_out[7:0] = regq8; |
|
case (opcode_in) |
`ORCC: |
CCRo = CCR | b_in[7:0]; |
`ANDCC: |
CCRo = CCR & b_in[7:0]; |
default: |
if (sz_in) // 16 bit |
CCRo = { CCR[7:4], n16, z16, v16, c16 }; |
else |
CCRo = { CCR[7:6], CCR[5], h8, n8, z8, v8, c8 }; |
endcase |
end |
|
initial |
begin |
end |
endmodule |
|
|
/* |
TERMS OF USE: MIT License |
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
of this software and associated documentation files (the "Software"), to deal |
in the Software without restriction, including without limitation the rights |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
copies of the Software, and to permit persons to whom the Software is |
furnished to do so, subject to the following conditions: |
|
The above copyright notice and this permission notice shall be included in |
all copies or substantial portions of the Software. |
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM, |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
THE SOFTWARE. |
*/ |
/rtl/verilog/BUGS.txt
0,0 → 1,9
Known bugs are described here |
|
28.12.13 |
-------- |
|
- EXG doesn't work, the register file can only be written once in the WriteBack cycle. |
- LEAX/LEAY do not modify the Z flag |
- The E flag is not read back when RTI is processed. This means that FIRQ will not return |
correctly. |
/sim/tb.v
0,0 → 1,237
/* MC6809/HD6309 Compatible core |
* (c) 2013 R.A. Paz Schmidt rapazschmidt@gmail.com |
* |
* Distributed under the terms of the Lesser GPL |
*/ |
`timescale 1ns/1ns |
`include "MC6809_cpu.v" |
`include "alu16.v" |
`include "decoders.v" |
`include "regblock.v" |
|
module tb(output wire [15:0] addr_o, output wire [7:0] data_o_o); |
|
reg clk, reset; |
|
assign addr_o = addr; |
assign data_o_o = data_o; |
wire [15:0] addr; |
wire [7:0] data_o, data_i; |
wire oe, we; |
always |
#5 clk = ~clk; |
|
MC6809_cpu cpu( |
.cpu_clk(clk), |
.cpu_reset_n(reset), |
.cpu_we_o(we), |
.cpu_oe_o(oe), |
.cpu_addr_o(addr), |
.cpu_data_i(data_i), |
.cpu_data_o(data_o) |
); |
|
memory imem(addr, !oe, !we, data_i, data_o); |
|
initial |
begin |
$dumpvars; |
clk = 0; |
reset = 0; |
#0 |
#46 |
reset = 1; |
#2000 |
$finish; |
end |
|
endmodule |
|
module memory( |
input wire [15:0] addr, |
input wire oe, |
input wire we, |
output wire [7:0] data_o, |
input wire [7:0] data_i |
); |
|
reg [7:0] mem[65535:0]; |
reg [7:0] latecheddata; |
wire [7:0] mem0, mem1, mem2, mem3; |
|
assign mem0 = mem[0]; |
assign mem1 = mem[1]; |
assign mem2 = mem[2]; |
assign mem3 = mem[3]; |
|
assign data_o = latecheddata; |
always @(negedge oe) |
latecheddata <= mem[addr]; |
|
always @(negedge we) |
begin |
mem[addr] <= data_i; |
$display("W %04x = %02x %t", addr, data_i, $time); |
end |
|
always @(negedge oe) |
begin |
$display("R %04x = %02x %t", addr, mem[addr], $time); |
end |
//`define READTESTBIN |
integer i; |
initial |
begin |
`ifdef READTESTBIN |
$readmemh("instructions_test.hex", mem); |
$display("instructions_test.hex read"); |
mem[16'hfffe] = 8'h00; // setup reset |
mem[16'hffff] = 8'h00; |
`else |
for (i = 0; i < 65536; i=i+1) |
mem[i] = 8'ha5; |
|
mem[16'h1000] = 8'h3f; // lda #$10 |
mem[16'h1001] = 8'h10; // |
mem[16'h1002] = 8'hc6; // ldb #$12 |
mem[16'h1003] = 8'h12; // |
|
mem[16'h1004] = 8'h3d; // mul |
mem[16'h1005] = 8'h4c; // inca |
mem[16'h1006] = 8'h5c; // incb |
|
mem[16'h1007] = 8'h9d; // jsr |
mem[16'h1008] = 8'h0e; // |
mem[16'h1009] = 8'h12; // nop |
|
mem[16'h100a] = 8'h20; // bre * |
mem[16'h100b] = 8'hfe; // |
mem[16'h100c] = 8'h12; // |
mem[16'h100d] = 8'h39; // |
mem[16'h100e] = 8'h39; // |
|
mem[16'h2000] = 8'h3b; // rti |
mem[16'h2002] = 8'h3b; // rti |
mem[16'h2004] = 8'h3b; // rti |
mem[16'h2006] = 8'h3b; // rti |
mem[16'h2008] = 8'h3b; // rti |
mem[16'h200a] = 8'h3b; // rti |
mem[16'h200c] = 8'h3b; // rti |
mem[16'h200e] = 8'h3b; // rti |
|
|
/* |
// test indexed store |
mem[16'h1000] = 8'h86; // lda #$fe |
mem[16'h1001] = 8'h02; // |
mem[16'h1002] = 8'h9e; // ldx $00 (direct) |
mem[16'h1003] = 8'h00; // |
|
mem[16'h1004] = 8'ha7; // lda ,x |
mem[16'h1005] = 8'b10000100; // ofs0 |
mem[16'h1006] = 8'ha7; // lda ,x+ |
mem[16'h1007] = 8'b10000000; // |
|
|
mem[16'h1008] = 8'ha7; // lda ,x++ |
mem[16'h1009] = 8'b10000001; // |
mem[16'h100a] = 8'ha6; // lda ,-x |
mem[16'h100b] = 8'b10000010; // |
|
mem[16'h100c] = 8'ha7; // lda ,--x |
mem[16'h100d] = 8'b10000011; // |
|
mem[16'h100e] = 8'ha7; // lda 0,x ofs 5 |
mem[16'h100f] = 8'h00; // |
|
mem[16'h1010] = 8'ha7; // lda 0,x ofs 8 |
mem[16'h1011] = 8'b10001000; // |
mem[16'h1012] = 8'h00; // |
|
mem[16'h1013] = 8'ha7; // lda 0,x ofs 16 |
mem[16'h1014] = 8'b10001001; // |
mem[16'h1015] = 8'h00; // |
mem[16'h1016] = 8'h00; // |
*/ |
|
/* test indexed load |
mem[16'h1000] = 8'h86; // lda #$02 |
mem[16'h1001] = 8'h02; // |
mem[16'h1002] = 8'h9e; // ldx $00 (direct) |
mem[16'h1003] = 8'h00; // |
|
mem[16'h1004] = 8'ha6; // lda ,x |
mem[16'h1005] = 8'b10000100; // ofs0 |
mem[16'h1006] = 8'ha6; // lda ,x+ |
mem[16'h1007] = 8'b10000000; // |
|
|
mem[16'h1008] = 8'ha6; // lda ,x++ |
mem[16'h1009] = 8'b10000001; // |
mem[16'h100a] = 8'ha6; // lda ,-x |
mem[16'h100b] = 8'b10000010; // |
|
mem[16'h100c] = 8'ha6; // lda ,--x |
mem[16'h100d] = 8'b10000011; // |
|
mem[16'h100e] = 8'ha6; // lda 0,x ofs 5 |
mem[16'h100f] = 8'h00; // |
|
mem[16'h1010] = 8'ha6; // lda 0,x ofs 8 |
mem[16'h1011] = 8'b10001000; // |
mem[16'h1012] = 8'h00; // |
|
mem[16'h1013] = 8'ha6; // lda 0,x ofs 16 |
mem[16'h1014] = 8'b10001001; // |
mem[16'h1015] = 8'h00; // |
mem[16'h1016] = 8'h00; // |
*/ |
|
/* test extended |
mem[16'h1000] = 8'hc6; // ldb #$fe |
mem[16'h1001] = 8'hfe; // |
mem[16'h1002] = 8'h86; // lda #$0 |
mem[16'h1003] = 8'h00; // |
|
mem[16'h1004] = 8'h4c; // inca |
mem[16'h1005] = 8'hb7; // sta $0000 |
mem[16'h1006] = 8'h00; // |
mem[16'h1007] = 8'h00; // |
|
|
mem[16'h1008] = 8'hb6; // lda $0000 |
mem[16'h1009] = 8'h00; // |
mem[16'h100a] = 8'h00; // |
|
mem[16'h100b] = 8'h26; // bne$.-5 |
mem[16'h100c] = 8'hf7; // |
|
mem[16'h100d] = 8'h5c; // incb |
|
mem[16'h100e] = 8'hf7; // stb $0001 |
mem[16'h100f] = 8'h00; // |
mem[16'h1010] = 8'h01; // |
|
mem[16'h1011] = 8'h20; // bra |
mem[16'h1012] = 8'hec; // $.-18 |
*/ |
mem[16'hfff0] = 8'h20; // reset |
mem[16'hfff1] = 8'h00; |
mem[16'hfff2] = 8'h20; // reset |
mem[16'hfff3] = 8'h02; |
mem[16'hfff4] = 8'h20; // reset |
mem[16'hfff5] = 8'h04; |
mem[16'hfff6] = 8'h20; // reset |
mem[16'hfff7] = 8'h06; |
mem[16'hfff8] = 8'h20; // reset |
mem[16'hfff9] = 8'h08; |
mem[16'hfffa] = 8'h20; // reset |
mem[16'hfffb] = 8'h0a; |
mem[16'hfffc] = 8'h20; // reset |
mem[16'hfffd] = 8'h0c; |
mem[16'hfffe] = 8'h10; // reset |
mem[16'hffff] = 8'h00; |
`endif |
end |
|
endmodule |
/sim/README.txt
0,0 → 1,9
MC6809/HD6309 compatible core. |
|
Simulation can be done with icarus verilog. |
|
$ iverilog tb.v ../rtl/verilog/*.v |
$ vvp a.out |
|
a dump file dump.vcd will be created. This file can be viewed with GTKWave. |
Simulation with other tools is also possible. |
/syn/lattice/logs/P6809_P6809_par.html
0,0 → 1,506
+}
+-->
+
+
+<HTML> |
<HEAD><TITLE>Place & Route Report</TITLE> |
<STYLE TYPE="text/css"> |
<!-- |
PAR: Place And Route Diamond (64-bit) 2.2.0.101. +Copyright (c) 1991-1994 by NeoCAD Inc. All rights reserved. +Copyright (c) 1995 AT&T Corp. All rights reserved. +Copyright (c) 1995-2001 Lucent Technologies Inc. All rights reserved. +Copyright (c) 2001 Agere Systems All rights reserved. +Copyright (c) 2002-2013 Lattice Semiconductor Corporation, All rights reserved. +Wed Dec 25 17:50:32 2013 + +/usr/local/diamond/2.2_x64/ispfpga/bin/lin64/par -f P6809_P6809.p2t +P6809_P6809_map.ncd P6809_P6809.dir P6809_P6809.prf + + +Preference file: P6809_P6809.prf. + +Cost Table Summary +Level/ Number Worst Timing Run NCD +Cost [ncd] Unrouted Slack Score Time Status +---------- -------- ----- -------- ----- ------ +5_1 * 0 -4.091 12558270 28 Complete + + +* : Design saved. + +Total (real) run time for 1-seed: 28 secs + +par done! + +Lattice Place and Route Report for Design "P6809_P6809_map.ncd" +Wed Dec 25 17:50:32 2013 + + +Best Par Run +PAR: Place And Route Diamond (64-bit) 2.2.0.101. +Command Line: par -w -l 5 -i 6 -t 1 -c 0 -e 0 -exp parUseNBR=1:parCDP=0:parCDR=0:parPathBased=OFF P6809_P6809_map.ncd P6809_P6809.dir/5_1.ncd P6809_P6809.prf +Preference file: P6809_P6809.prf. +Placement level-cost: 5-1. +Routing Iterations: 6 + +Loading design for application par from file P6809_P6809_map.ncd. +Design name: CC3_top +NCD version: 3.2 +Vendor: LATTICE +Device: LCMXO2-7000HE +Package: TQFP144 +Performance: 4 +Loading device for application par from file 'xo2c7000.nph' in environment: /usr/local/diamond/2.2_x64/ispfpga. +Package Status: Final Version 1.36 +Performance Hardware Data Status: Final) Version 23.4 +License checked out. + + +Ignore Preference Error(s): True + +Device utilization summary: + + PIO (prelim) 49+4(JTAG)/336 14% used + 49+4(JTAG)/115 42% bonded + IOLOGIC 8/336 2% used + + SLICE 1163/3432 33% used + + GSR 1/1 100% used + EBR 2/26 7% used + + +INFO: Design contains EBR with ASYNC Reset Mode that has a limitation: The use of the EBR block asynchronous reset requires that certain timing be met between the clock and the reset within the memory block. See the device specific datasheet for additional details. +INFO: Design contains pre-loadable EBR during configuration that has a requirement: Since the GSR is disabled for the EBR, make sure write enable and chip enable are inactive during wake-up, so that the pre-loaded initialization values will not be corrupted during wake-up state. +Number of Signals: 2675 +Number of Connections: 8924 + +Pin Constraint Summary: + 49 out of 49 pins locked (100% locked). + +The following 1 signal is selected to use the primary clock routing resources: + cpu_clkgen (driver: clk40_i, clk load #: 315) + + +The following 6 signals are selected to use the secondary clock routing resources: + cpu_clk (driver: SLICE_477, clk load #: 0, sr load #: 0, ce load #: 95) + cpu0/cff_1_sqmuxa_0_RNIL5DT (driver: cpu0/SLICE_865, clk load #: 0, sr load #: 0, ce load #: 43) + cpu0/regs/regh[4]_1_sqmuxa_1_1_RNI7MAL1 (driver: cpu0/regs/SLICE_829, clk load #: 0, sr load #: 0, ce load #: 12) + cpu0/regs/regh[3]_1_sqmuxa_3_0_RNI9DKR1 (driver: cpu0/regs/SLICE_830, clk load #: 0, sr load #: 0, ce load #: 12) + cpu0/regs/regh[2]_0_sqmuxa_i_a2_1_RNIJL6H2 (driver: cpu0/regs/SLICE_887, clk load #: 0, sr load #: 0, ce load #: 12) + cpu0/regs/regh[1]_0_sqmuxa_1_i_a2_2_RNI192E2 (driver: cpu0/regs/SLICE_886, clk load #: 0, sr load #: 0, ce load #: 12) + +Signal cpu0.cpu_reset_i_2_i is selected as Global Set/Reset. +Starting Placer Phase 0. +.......... +Finished Placer Phase 0. REAL time: 4 secs + +Starting Placer Phase 1. +...................... +Placer score = 808498. +Finished Placer Phase 1. REAL time: 12 secs + +Starting Placer Phase 2. +. +Placer score = 797364 +Finished Placer Phase 2. REAL time: 13 secs + + + +Clock Report + +Global Clock Resources: + CLK_PIN : 1 out of 8 (12%) + PLL : 0 out of 2 (0%) + DCM : 0 out of 2 (0%) + DCC : 0 out of 8 (0%) + +Quadrants All (TL, TR, BL, BR) - Global Clocks: + PRIMARY "cpu_clkgen" from comp "clk40_i" on CLK_PIN site "27 (PL22A)", clk load = 315 + SECONDARY "cpu_clk" from Q0 on comp "SLICE_477" on site "R21C20B", clk load = 0, ce load = 95, sr load = 0 + SECONDARY "cpu0/cff_1_sqmuxa_0_RNIL5DT" from F0 on comp "cpu0/SLICE_865" on site "R14C18A", clk load = 0, ce load = 43, sr load = 0 + SECONDARY "cpu0/regs/regh[4]_1_sqmuxa_1_1_RNI7MAL1" from F1 on comp "cpu0/regs/SLICE_829" on site "R21C18C", clk load = 0, ce load = 12, sr load = 0 + SECONDARY "cpu0/regs/regh[3]_1_sqmuxa_3_0_RNI9DKR1" from F1 on comp "cpu0/regs/SLICE_830" on site "R14C18D", clk load = 0, ce load = 12, sr load = 0 + SECONDARY "cpu0/regs/regh[2]_0_sqmuxa_i_a2_1_RNIJL6H2" from F0 on comp "cpu0/regs/SLICE_887" on site "R14C18B", clk load = 0, ce load = 12, sr load = 0 + SECONDARY "cpu0/regs/regh[1]_0_sqmuxa_1_i_a2_2_RNI192E2" from F0 on comp "cpu0/regs/SLICE_886" on site "R14C18C", clk load = 0, ce load = 12, sr load = 0 + + PRIMARY : 1 out of 8 (12%) + SECONDARY: 6 out of 8 (75%) + +Edge Clocks: + No edge clock selected. + + + + +I/O Usage Summary (final): + 49 out of 336 (14.6%) PIO sites used. + 49 out of 115 (42.6%) bonded PIO sites used. + Number of PIO comps: 49; differential: 0 + Number of Vref pins used: 0 + +I/O Bank Usage Summary: ++----------+----------------+------------+-----------+ +| I/O Bank | Usage | Bank Vccio | Bank Vref | ++----------+----------------+------------+-----------+ +| 0 | 12 / 28 ( 42%) | 2.5V | - | +| 1 | 13 / 29 ( 44%) | 2.5V | - | +| 2 | 23 / 29 ( 79%) | 2.5V | - | +| 3 | 1 / 9 ( 11%) | 2.5V | - | +| 4 | 0 / 10 ( 0%) | - | - | +| 5 | 0 / 10 ( 0%) | - | - | ++----------+----------------+------------+-----------+ + +Total placer CPU time: 12 secs + +Dumping design to file P6809_P6809.dir/5_1.ncd. + +0 connections routed; 8924 unrouted. +Starting router resource preassignment + +Completed router resource preassignment. Real time: 16 secs + +Start NBR router at Wed Dec 25 17:50:48 CET 2013 + +***************************************************************** +Info: NBR allows conflicts(one node used by more than one signal) + in the earlier iterations. In each iteration, it tries to + solve the conflicts while keeping the critical connections + routed as short as possible. The routing process is said to + be completed when no conflicts exist and all connections + are routed. +Note: NBR uses a different method to calculate timing slacks. The + worst slack and total negative slack may not be the same as + that in TRCE report. You should always run TRCE to verify + your design. Thanks. +***************************************************************** + +Start NBR special constraint process at Wed Dec 25 17:50:48 CET 2013 + +Start NBR section for initial routing +Level 1, iteration 1 +137(0.04%) conflicts; 7446(83.44%) untouched conns; 1425225 (nbr) score; +Estimated worst slack/total negative slack: -3.332ns/-1425.225ns; real time: 18 secs +Level 2, iteration 1 +162(0.04%) conflicts; 6336(71.00%) untouched conns; 1178362 (nbr) score; +Estimated worst slack/total negative slack: -3.339ns/-1178.363ns; real time: 19 secs +Level 3, iteration 1 +89(0.02%) conflicts; 5385(60.34%) untouched conns; 1500920 (nbr) score; +Estimated worst slack/total negative slack: -3.347ns/-1500.921ns; real time: 20 secs +Level 4, iteration 1 +349(0.09%) conflicts; 0(0.00%) untouched conn; 1551317 (nbr) score; +Estimated worst slack/total negative slack: -3.425ns/-1551.318ns; real time: 21 secs + +Info: Initial congestion level at 75% usage is 0 +Info: Initial congestion area at 75% usage is 5 (0.50%) + +Start NBR section for normal routing +Level 1, iteration 1 +88(0.02%) conflicts; 402(4.50%) untouched conns; 1210645 (nbr) score; +Estimated worst slack/total negative slack: -3.167ns/-1210.645ns; real time: 21 secs +Level 4, iteration 1 +237(0.06%) conflicts; 0(0.00%) untouched conn; 1243629 (nbr) score; +Estimated worst slack/total negative slack: -3.155ns/-1243.630ns; real time: 22 secs +Level 4, iteration 2 +131(0.03%) conflicts; 0(0.00%) untouched conn; 1252609 (nbr) score; +Estimated worst slack/total negative slack: -3.245ns/-1252.609ns; real time: 23 secs +Level 4, iteration 3 +97(0.03%) conflicts; 0(0.00%) untouched conn; 1308083 (nbr) score; +Estimated worst slack/total negative slack: -3.416ns/-1308.084ns; real time: 23 secs +Level 4, iteration 4 +71(0.02%) conflicts; 0(0.00%) untouched conn; 1308083 (nbr) score; +Estimated worst slack/total negative slack: -3.416ns/-1308.084ns; real time: 23 secs +Level 4, iteration 5 +71(0.02%) conflicts; 0(0.00%) untouched conn; 1426563 (nbr) score; +Estimated worst slack/total negative slack: -3.558ns/-1426.563ns; real time: 24 secs +Level 4, iteration 6 +50(0.01%) conflicts; 0(0.00%) untouched conn; 1426563 (nbr) score; +Estimated worst slack/total negative slack: -3.558ns/-1426.563ns; real time: 24 secs +Level 4, iteration 7 +30(0.01%) conflicts; 0(0.00%) untouched conn; 1480393 (nbr) score; +Estimated worst slack/total negative slack: -3.626ns/-1480.394ns; real time: 24 secs +Level 4, iteration 8 +23(0.01%) conflicts; 0(0.00%) untouched conn; 1480393 (nbr) score; +Estimated worst slack/total negative slack: -3.626ns/-1480.394ns; real time: 24 secs +Level 4, iteration 9 +17(0.00%) conflicts; 0(0.00%) untouched conn; 1550078 (nbr) score; +Estimated worst slack/total negative slack: -3.626ns/-1550.079ns; real time: 24 secs +Level 4, iteration 10 +16(0.00%) conflicts; 0(0.00%) untouched conn; 1550078 (nbr) score; +Estimated worst slack/total negative slack: -3.626ns/-1550.079ns; real time: 24 secs +Level 4, iteration 11 +15(0.00%) conflicts; 0(0.00%) untouched conn; 1549789 (nbr) score; +Estimated worst slack/total negative slack: -3.656ns/-1549.790ns; real time: 25 secs +Level 4, iteration 12 +17(0.00%) conflicts; 0(0.00%) untouched conn; 1549789 (nbr) score; +Estimated worst slack/total negative slack: -3.656ns/-1549.790ns; real time: 25 secs +Level 4, iteration 13 +9(0.00%) conflicts; 0(0.00%) untouched conn; 1540315 (nbr) score; +Estimated worst slack/total negative slack: -3.634ns/-1540.316ns; real time: 25 secs +Level 4, iteration 14 +7(0.00%) conflicts; 0(0.00%) untouched conn; 1540315 (nbr) score; +Estimated worst slack/total negative slack: -3.634ns/-1540.316ns; real time: 25 secs +Level 4, iteration 15 +6(0.00%) conflicts; 0(0.00%) untouched conn; 1564368 (nbr) score; +Estimated worst slack/total negative slack: -3.626ns/-1564.369ns; real time: 25 secs +Level 4, iteration 16 +6(0.00%) conflicts; 0(0.00%) untouched conn; 1564368 (nbr) score; +Estimated worst slack/total negative slack: -3.626ns/-1564.369ns; real time: 25 secs +Level 4, iteration 17 +6(0.00%) conflicts; 0(0.00%) untouched conn; 1543739 (nbr) score; +Estimated worst slack/total negative slack: -3.634ns/-1543.739ns; real time: 25 secs +Level 4, iteration 18 +7(0.00%) conflicts; 0(0.00%) untouched conn; 1543739 (nbr) score; +Estimated worst slack/total negative slack: -3.634ns/-1543.739ns; real time: 25 secs +Level 4, iteration 19 +6(0.00%) conflicts; 0(0.00%) untouched conn; 1539700 (nbr) score; +Estimated worst slack/total negative slack: -3.626ns/-1539.701ns; real time: 25 secs +Level 4, iteration 20 +4(0.00%) conflicts; 0(0.00%) untouched conn; 1539700 (nbr) score; +Estimated worst slack/total negative slack: -3.626ns/-1539.701ns; real time: 25 secs +Level 4, iteration 21 +4(0.00%) conflicts; 0(0.00%) untouched conn; 1541625 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1541.626ns; real time: 25 secs +Level 4, iteration 22 +2(0.00%) conflicts; 0(0.00%) untouched conn; 1541625 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1541.626ns; real time: 26 secs +Level 4, iteration 23 +1(0.00%) conflict; 0(0.00%) untouched conn; 1553537 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1553.538ns; real time: 26 secs +Level 4, iteration 24 +5(0.00%) conflicts; 0(0.00%) untouched conn; 1553537 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1553.538ns; real time: 26 secs +Level 4, iteration 25 +3(0.00%) conflicts; 0(0.00%) untouched conn; 1631557 (nbr) score; +Estimated worst slack/total negative slack: -3.805ns/-1631.557ns; real time: 26 secs +Level 4, iteration 26 +1(0.00%) conflict; 0(0.00%) untouched conn; 1631557 (nbr) score; +Estimated worst slack/total negative slack: -3.805ns/-1631.557ns; real time: 26 secs +Level 4, iteration 27 +1(0.00%) conflict; 0(0.00%) untouched conn; 1553196 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1553.197ns; real time: 26 secs +Level 4, iteration 28 +1(0.00%) conflict; 0(0.00%) untouched conn; 1553196 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1553.197ns; real time: 26 secs +Level 4, iteration 29 +1(0.00%) conflict; 0(0.00%) untouched conn; 1553196 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1553.197ns; real time: 26 secs +Level 4, iteration 30 +1(0.00%) conflict; 0(0.00%) untouched conn; 1553196 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1553.197ns; real time: 26 secs +Level 4, iteration 31 +1(0.00%) conflict; 0(0.00%) untouched conn; 1553196 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1553.197ns; real time: 26 secs +Level 4, iteration 32 +1(0.00%) conflict; 0(0.00%) untouched conn; 1553196 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1553.197ns; real time: 26 secs +Level 4, iteration 33 +1(0.00%) conflict; 0(0.00%) untouched conn; 1553196 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1553.197ns; real time: 26 secs +Level 4, iteration 34 +0(0.00%) conflict; 0(0.00%) untouched conn; 1553196 (nbr) score; +Estimated worst slack/total negative slack: -3.627ns/-1553.197ns; real time: 26 secs + +Start NBR section for performance tunning (iteration 1) +Level 4, iteration 1 +4(0.00%) conflicts; 0(0.00%) untouched conn; 1791659 (nbr) score; +Estimated worst slack/total negative slack: -4.091ns/-1791.660ns; real time: 27 secs + +Start NBR section for re-routing +Level 4, iteration 1 +0(0.00%) conflict; 0(0.00%) untouched conn; 1793776 (nbr) score; +Estimated worst slack/total negative slack: -4.091ns/-1793.777ns; real time: 27 secs + +Start NBR section for post-routing + +End NBR router with 0 unrouted connection + +NBR Summary +----------- + Number of unrouted connections : 0 (0.00%) + Number of connections with timing violations : 938 (10.51%) + Estimated worst slack : -4.091ns + Timing score : 12558270 +----------- +Notes: The timing info is calculated for SETUP only and all PAR_ADJs are ignored. + + + +------------------------------------------------------------------------------------------------------------------------------------ +WARNING - par: Hold timing correction is skipped because the worst (setup) slack(-4.091ns) is worse than the default value(0.000ns). +------------------------------------------------------------------------------------------------------------------------------------ + +Total CPU time 28 secs +Total REAL time: 28 secs +Completely routed. +End of route. 8924 routed (100.00%); 0 unrouted. +Checking DRC ... +No errors found. + +Hold time timing score: 0, hold timing errors: 0 + +Timing score: 12558270 + +Dumping design to file P6809_P6809.dir/5_1.ncd. + + +All signals are completely routed. + + +PAR_SUMMARY::Run status = completed +PAR_SUMMARY::Number of unrouted conns = 0 +PAR_SUMMARY::Worst slack+> = -4.091 +PAR_SUMMARY::Timing score > = 12558.270 +PAR_SUMMARY::Worst slack > = +PAR_SUMMARY::Timing score > = + +Total CPU time to completion: 28 secs +Total REAL time to completion: 28 secs + +par done! + +Copyright (c) 1991-1994 by NeoCAD Inc. All rights reserved. +Copyright (c) 1995 AT&T Corp. All rights reserved. +Copyright (c) 1995-2001 Lucent Technologies Inc. All rights reserved. +Copyright (c) 2001 Agere Systems All rights reserved. +Copyright (c) 2002-2013 Lattice Semiconductor Corporation, All rights reserved. + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+