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/rtl
- from Rev 16 to Rev 17
- ↔ Reverse comparison
Rev 16 → Rev 17
/verilog/MC6809_cpu.v
5,7 → 5,7
* distributed under the terms of the Lesser GPL, see LICENSE.TXT |
* |
*/ |
|
|
`include "defs.v" |
module MC6809_cpu( |
input wire cpu_clk, |
18,16 → 18,16
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, |
input wire debug_clk, |
output wire [7:0] cpu_data_o, |
input wire debug_clk, |
output wire debug_data_o // serial debug info, 64 bit shift register |
|
|
); |
|
|
wire k_reset; |
|
|
reg [7:0] k_opcode, k_postbyte, k_ind_ea; /* all bytes of an instruction */ |
reg [7:0] k_pp_regs; // push/pull registers to process |
reg [7:0] k_pp_regs; // push/pull registers to process |
reg [3:0] k_pp_active_reg; // push/pull active register |
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; |
34,15 → 34,15
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 |
next_push_state; // next state to exit to from push multiple state machine |
reg k_write_tfr, k_write_exg; |
reg k_cpu_oe, k_cpu_we, k_inc_pc; |
reg k_indirect_loaded; // set when in indirect indexed and the address has been loaded |
reg [15:0] k_cpu_addr, k_new_pc; |
reg k_write_pc, k_inc_su, k_dec_su, k_set_e, k_clear_e; |
reg k_mul_cnt; // multiplier couner |
reg k_write_pc, k_inc_su, k_dec_su, k_set_e, k_clear_e; |
reg k_mul_cnt; // multiplier couner |
reg k_write_dest; // set for 1 clock when a register has to be written, dec_o_dest_reg_addr has the register source |
reg k_write_post_incdec; // asserted when in the last write cycle or in write back for loads |
reg k_write_post_incdec; // asserted when in the last write cycle or in write back for loads |
reg k_forced_mem_size; // used to force the size of a memory read to be 16 bits, used for vector fetch |
/**** |
* Decoder outputs |
52,7 → 52,7
wire dec_o_alu_size; /* size of the result of an alu opcode (destination to be written) */ |
wire op_SYNC, op_EXG, op_TFR, op_RTS, op_RTI, op_CWAI; |
wire op_MUL, op_SWI, op_PUSH, op_PULL, op_LEA, op_JMP, op_JSR; |
|
|
/* ea decoder */ |
wire dec_o_ea_ofs8, dec_o_ea_ofs16, dec_o_ea_wpost, dec_o_ea_ofs5, dec_o_ea_indirect; |
wire [3:0] dec_o_eabase, dec_o_eaidx; |
80,46 → 80,46
- * Interrupt sync registers
+
+/*
+ * 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];
-
-/* Debug */
-`ifdef SERIAL_DEBUG
-reg [63:0] debug_r;
-
-always @(posedge debug_clk)
- begin
- if (cpu_clk)
- begin
- debug_r[15:0] <= regs_o_pc;
- debug_r[23:16] <= k_opcode;
- debug_r[27:24] <= datamux_o_alu_in_left_path_addr;
- debug_r[31:28] <= dec_o_right_path_addr;
- debug_r[35:32] <= datamux_o_dest_reg_addr;
- debug_r[39:36] <= { 3'b0, k_write_pc }; //regs_o_CCR[3:0];
- debug_r[55:40] <= { k_memhi,k_memlo };//k_new_pc;
- debug_r[63:56] <= cpu_data_i;
- end
- else
- debug_r <= debug_r << 1; // shift out
- end
-
-assign debug_data_o = debug_r[63];
-`else
-assign debug_data_o = 1'b0;
+
+/* Debug */
+`ifdef SERIAL_DEBUG
+reg [63:0] debug_r;
+
+always @(posedge debug_clk)
+ begin
+ if (cpu_clk)
+ begin
+ debug_r[15:0] <= regs_o_pc;
+ debug_r[23:16] <= k_opcode;
+ debug_r[27:24] <= datamux_o_alu_in_left_path_addr;
+ debug_r[31:28] <= dec_lo_right_path_addr;
+ debug_r[35:32] <= datamux_o_dest_reg_addr;
+ debug_r[39:36] <= { 3'b0, k_write_pc }; //regs_o_CCR[3:0];
+ debug_r[55:40] <= { k_memhi,k_memlo };//k_new_pc;
+ debug_r[63:56] <= cpu_data_i;
+ end
+ else
+ debug_r <= debug_r << 1; // shift out
+ end
+
+assign debug_data_o = debug_r[63];
+`else
+assign debug_data_o = 1'b0;
`endif
alu alu(
.clk_in(cpu_clk),
@@ -126,18 +126,18 @@
.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 */
+ .opcode_in(dec_o_alu_opcode), /* ALU k_opcode */
.sz_in(dec_o_alu_size),
.q_out(alu_o_result), /* ALU result */
.CCRo(alu_o_CCR)
- );
-
-
+ );
+
+
regblock regs(
.clk_in(cpu_clk),
.path_left_addr(datamux_o_alu_in_left_path_addr),
.path_right_addr(dec_lo_right_path_addr),
- .write_reg_addr(datamux_o_dest_reg_addr),
+ .write_reg_addr(datamux_o_dest_reg_addr),
.exg_dest_r(k_postbyte[7:4]),
.eapostbyte( k_ind_ea ),
.offset16({ k_ofshi, k_ofslo }),
@@ -170,10 +170,6 @@
.postbyte0(k_postbyte),
.page2_valid(k_p2_valid),
.page3_valid(k_p3_valid),
-
- .path_left_addr_o(dec_o_left_path_addr),
- .path_right_addr_o(dec_o_right_path_addr),
- .dest_reg_o(dec_o_dest_reg_addr),
.path_left_addr_lo(dec_lo_left_path_addr),
.path_right_addr_lo(dec_lo_right_path_addr),
.dest_reg_lo(dec_lo_dest_reg_addr),
@@ -206,7 +202,7 @@
.alu_opcode(dec_o_alu_opcode),
.dest_flags_o(dec_o_write_flags)
);
-
+
decode_ea dec_ea(
.eapostbyte( k_ind_ea ),
.eabase_o(dec_o_eabase), // base register
@@ -217,8 +213,8 @@
.ea_is_indirect_o(dec_o_ea_indirect),
.ea_write_back_o(dec_o_ea_wpost)
);
-
-
+
+
/* Condition decoder */
test_condition test_cond(
.opcode(k_opcode),
@@ -227,9 +223,9 @@
.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;
@@ -236,28 +232,28 @@
assign cpu_data_o = k_cpu_data_o;
assign k_reset = cpu_reset;
assign cpu_state_o = state;
-
+
wire cpu_dtack_i = 1;
/* Left Register read mux
*/
always @(*)
- begin
+ begin
if (k_pp_active_reg != `RN_INV)
datamux_o_alu_in_left_path_addr = k_pp_active_reg;
else
datamux_o_alu_in_left_path_addr = dec_lo_left_path_addr;
end
-
+
/* Destination register address MUX
*/
always @(*)
- begin
- if (k_pp_active_reg != `RN_INV)
- datamux_o_dest_reg_addr = k_pp_active_reg;
- else
- datamux_o_dest_reg_addr = dec_lo_dest_reg_addr;
+ begin
+ if (k_pp_active_reg != `RN_INV)
+ datamux_o_dest_reg_addr = k_pp_active_reg;
+ else
+ datamux_o_dest_reg_addr = dec_lo_dest_reg_addr;
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
*
@@ -277,9 +273,9 @@
else
datamux_o_dest = alu_o_result;
end
-
+
/* ALU left input mux */
-
+
always @(*)
begin
if (dec_lo_left_path_memtype == `MT_BYTE)
@@ -294,17 +290,17 @@
end
else
datamux_o_alu_in_left_path_data = regs_o_left_path_data;
- end
+ end
/* PC as destination from jmp/bsr mux */
-always @(*)
- begin
- k_new_pc = { k_memhi,k_memlo }; // used to fetch reset vector
+always @(*)
+ begin
+ k_new_pc = { k_memhi,k_memlo }; // used to fetch reset vector
case (dec_o_p1_mode)
`REL16: k_new_pc = regs_o_pc + { k_memhi,k_memlo };
`REL8: k_new_pc = regs_o_pc + { {8{k_memlo[7]}}, k_memlo };
`EXTENDED: k_new_pc = { k_eahi,k_ealo };
`DIRECT: k_new_pc = { regs_o_dp, k_ealo };
- `INDEXED:
+ `INDEXED:
if (dec_o_ea_indirect)
k_new_pc = { k_memhi,k_memlo };
else
@@ -311,7 +307,7 @@
k_new_pc = regs_o_eamem_addr;
default:
k_new_pc = { k_memhi,k_memlo }; // used to fetch reset vector
- endcase
+ endcase
end
/* ALU right input mux */
always @(*)
@@ -326,7 +322,7 @@
// datamux_o_alu_in_right_path_data = { k_memhi, k_memlo };
// endcase
end
-
+
always @(posedge cpu_clk or posedge k_reset)
begin
if (k_reset == 1'b1)
@@ -363,16 +359,16 @@
if (k_set_e)
k_set_e <= 0;
if (k_clear_e)
- k_clear_e <= 0;
- if (k_write_dest)
- k_write_dest <= 0;
- if (k_write_exg)
- k_write_exg <= 0;
+ k_clear_e <= 0;
+ if (k_write_dest)
+ k_write_dest <= 0;
+ if (k_write_exg)
+ k_write_exg <= 0;
if (k_write_tfr)
k_write_tfr <= 0;
case (state)
`SEQ_COLDRESET:
- begin
+ begin
k_forced_mem_size <= 1;
state <= `SEQ_MEM_READ_H;
k_eahi <= 8'hff;
@@ -607,13 +603,13 @@
end
else
next_state <= `SEQ_GRAL_ALU; // no read
- k_eahi <= regs_o_dp;
+ k_eahi <= regs_o_dp;
end
end
`INDEXED:
state <= `SEQ_IND_READ_EA;
`EXTENDED:
- begin
+ begin
state <= `SEQ_PC_READ_H; // loads address
if (op_JSR) next_state <= `SEQ_JSR_PUSH;
else if (op_JMP) next_state <= `SEQ_JMP_LOAD_PC;
@@ -625,7 +621,7 @@
next_mem_state <= `SEQ_GRAL_ALU; // read then alu
end
else
- next_state <= `SEQ_GRAL_ALU; // no read
+ next_state <= `SEQ_GRAL_ALU; // no read
end
end
`REL8:
@@ -646,18 +642,18 @@
end
endcase
end
- `SEQ_GRAL_ALU:
- begin
- if (!k_mul_cnt)
+ `SEQ_GRAL_ALU:
+ begin
+ if (!k_mul_cnt)
begin
- state <= `SEQ_GRAL_WBACK;
- k_write_dest <= 1; /* write destination on wback */
- end
+ state <= `SEQ_GRAL_WBACK;
+ k_write_dest <= 1; /* write destination on wback */
+ end
k_mul_cnt <= 1'h0;
end
`SEQ_GRAL_WBACK:
begin
- next_mem_state <= `SEQ_FETCH;
+ next_mem_state <= `SEQ_FETCH;
if (op_CWAI) state <= `SEQ_CWAI_STACK; // CWAI
else if (dec_o_dest_memtype == `MT_BYTE) state <= `SEQ_MEM_WRITE_L;
else if (dec_o_dest_memtype == `MT_WORD) state <= `SEQ_MEM_WRITE_H;
@@ -665,26 +661,26 @@
begin
state <= `SEQ_FETCH;
k_write_post_incdec <= dec_o_ea_wpost & (dec_o_p1_mode == `INDEXED);
- end
+ end
end
`SEQ_CWAI_STACK:
- begin
+ begin
k_pp_regs <= 8'hff;
k_set_e <= 1;
state <= `SEQ_PREPUSH; // first stack the registers
- next_push_state <= `SEQ_CWAI_WAIT; // wait for interrupts
- end
- `SEQ_CWAI_WAIT: /* waits for an interrupt and process it */
- begin
+ next_push_state <= `SEQ_CWAI_WAIT; // wait for interrupts
+ end
+ `SEQ_CWAI_WAIT: /* waits for an interrupt and process it */
+ begin
k_forced_mem_size <= 1;
- next_mem_state <= `SEQ_FETCH; // then continue fetching instructions
- k_eahi <= 8'hff;
+ next_mem_state <= `SEQ_FETCH; // then continue fetching instructions
+ k_eahi <= 8'hff;
k_ealo[7:4] <= 4'hf;
- if (k_nmi_req)
+ if (k_nmi_req)
begin
k_reg_nmi <= 3'h0;
k_ealo[3:0] <= 4'hc;
- state <= `SEQ_MEM_READ_H; // load new PC
+ state <= `SEQ_MEM_READ_H; // load new PC
end
else
if (k_firq_req & `FLAGF)
@@ -700,26 +696,26 @@
k_ealo[3:0] <= 4'h8;
state <= `SEQ_MEM_READ_H; // load new PC
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
+ 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
+ state <= `SEQ_NMI;
+ else
+ begin
+ state <= `SEQ_FETCH;
+ k_reg_nmi <= 3'h0;
+ end
end
else
- if (k_firq_req & `FLAGF)
+ if (k_firq_req & `FLAGF)
begin
if (k_reg_firq == 3'b111) // at least 3 cycles long
state <= `SEQ_FIRQ;
@@ -727,10 +723,10 @@
begin
state <= `SEQ_FETCH;
k_reg_firq <= 3'h0;
- end
+ end
end
else
- if (k_irq_req & `FLAGI)
+ if (k_irq_req & `FLAGI)
begin
if (k_reg_irq == 3'b111) // at least 3 cycles long
state <= `SEQ_IRQ;
@@ -744,9 +740,9 @@
begin
state <= `SEQ_FETCH_1;
k_cpu_addr <= regs_o_pc;
- end
+ end
end
- `SEQ_TFREXG:
+ `SEQ_TFREXG:
state <= `SEQ_FETCH;
`SEQ_IND_READ_EA: // reads EA byte
begin
@@ -795,7 +791,7 @@
end
end
`SEQ_IND_DECODE_OFS: // loads argument if needed
- begin
+ begin
if (op_JSR) // jsr
next_state <= `SEQ_JSR_PUSH;
else
@@ -808,12 +804,21 @@
k_forced_mem_size <= 1; // to load indirect address
end
else
- state <= `SEQ_GRAL_ALU; // no load, then store
+ state <= `SEQ_GRAL_ALU; // no load, then store
end
end
`SEQ_JMP_LOAD_PC:
begin
state <= `SEQ_FETCH;
+`ifdef CODE_ANALYSIS
+ if (op_JSR)
+ $display("J JSR [%x]", k_new_pc);
+ else
+ if (op_JMP)
+ $display("J JUMP[%x]", k_new_pc);
+ else
+ $display("R JUMP[%x]", k_new_pc);
+`endif
end
`SEQ_JSR_PUSH:
begin
@@ -824,9 +829,9 @@
`SEQ_PREPUSH:
begin
next_state <= `SEQ_PREPUSH;
- if (k_pp_regs > 0)
+ if (k_pp_regs > 0)
begin
- state <= `SEQ_PUSH_WRITE_L;
+ state <= `SEQ_PUSH_WRITE_L;
end
else
state <= next_push_state;
@@ -847,20 +852,20 @@
if (k_pp_regs[0]) begin k_pp_regs[0] <= 0; k_pp_active_reg <= `RN_CC; end
end
`SEQ_PREPULL:
- begin
- if (k_pp_regs != 8'h0)
+ begin
+ if (k_pp_regs != 8'h0)
begin
- next_mem_state <= `SEQ_PREPULL;
- end
- else
+ next_mem_state <= `SEQ_PREPULL;
+ end
+ else
state <= `SEQ_FETCH; // end of sequence
if (k_pp_regs[0]) begin k_pp_active_reg <= `RN_CC; k_pp_regs[0] <= 0; state <= `SEQ_MEM_READ_L; end
- else
- if (op_RTI && (!`FLAGE)) // not all registers have to be pulled
- begin
- k_pp_active_reg <= `RN_PC; k_pp_regs <= 0; state <= `SEQ_MEM_READ_H;
- end
else
+ if (op_RTI && (!`FLAGE)) // not all registers have to be pulled
+ begin
+ k_pp_active_reg <= `RN_PC; k_pp_regs <= 0; state <= `SEQ_MEM_READ_H;
+ end
+ else
if (k_pp_regs[1]) begin k_pp_active_reg <= `RN_ACCA; k_pp_regs[1] <= 0; state <= `SEQ_MEM_READ_L; end
else
if (k_pp_regs[2]) begin k_pp_active_reg <= `RN_ACCB; k_pp_regs[2] <= 0; state <= `SEQ_MEM_READ_L; end
@@ -880,7 +885,7 @@
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 - 16'h1;
+ k_cpu_addr <= regs_o_su - 16'h1;
k_dec_su <= 1;
end
`SEQ_PUSH_WRITE_L_1:
@@ -891,7 +896,7 @@
if (k_pp_regs[3:0] > 0)
state <= `SEQ_PREPUSH;
else
- state <= next_push_state;
+ state <= next_push_state;
k_cpu_addr <= k_cpu_addr - 16'h1; // when pushing 16 bits the second decrement comes too late
end
`SEQ_PUSH_WRITE_H: // reads high byte
@@ -898,13 +903,13 @@
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_we <= 1; // write
if (k_pp_active_reg >= `RN_ACCA)
k_cpu_addr <= regs_o_su; // address for 8 bit register
k_dec_su <= 1; // decrement stack pointer
end
`SEQ_PUSH_WRITE_H_1:
- begin
+ begin
if (next_state == `SEQ_JMP_LOAD_PC)
k_write_pc <= 1; // load PC in the next cycle, the mux output will have the right source
state <= next_state;
@@ -947,8 +952,8 @@
`REL8, `REL16, `IMMEDIATE: k_memlo <= cpu_data_i;
`DIRECT, `EXTENDED: k_ealo <= cpu_data_i;
`INDEXED: k_ofslo <= cpu_data_i;
- endcase
- if ((next_state == `SEQ_JMP_LOAD_PC) & (dec_o_cond_taken))
+ endcase
+ if ((next_state == `SEQ_JMP_LOAD_PC) & (dec_o_cond_taken))
k_write_pc <= 1; // load PC in the next cycle, the mux output will have the right source
state <= next_state;
end
@@ -968,11 +973,11 @@
end
else
k_cpu_addr <= { k_eahi, k_ealo };
- endcase
+ endcase
if (k_forced_mem_size | dec_o_source_size | (k_pp_active_reg < `RN_ACCA))
- state <= `SEQ_MEM_READ_H_1;
- else
- state <= `SEQ_MEM_READ_L_1;
+ state <= `SEQ_MEM_READ_H_1;
+ else
+ state <= `SEQ_MEM_READ_L_1;
k_forced_mem_size <= 0; // used for vector fetch
end
`SEQ_MEM_READ_H_1:
@@ -984,13 +989,13 @@
begin
k_memhi <= cpu_data_i;
state <= `SEQ_MEM_READ_L_1;
- k_cpu_addr <= k_cpu_addr + 16'h1;
+ k_cpu_addr <= k_cpu_addr + 16'h1;
if (op_PULL | op_RTI | op_RTS)
k_inc_su <= 1;
end
`SEQ_MEM_READ_L: // reads low byte
begin
- // falls through from READ_MEM_H with the right address
+ // falls through from READ_MEM_H with the right address
if (op_PULL | op_RTI | op_RTS)
begin
k_cpu_addr <= regs_o_su;
@@ -1006,8 +1011,8 @@
`SEQ_MEM_READ_L_2:
begin
k_memlo <= cpu_data_i;
- if (op_PULL | op_RTI | op_RTS) k_write_dest <= 1; // FIXME: which other opcode is inherent and needs write-back ?
- if (next_mem_state == `SEQ_LOADPC) // used by cold-reset
+ if (op_PULL | op_RTI | op_RTS) k_write_dest <= 1; // FIXME: which other opcode is inherent and needs write-back ?
+ if (next_mem_state == `SEQ_LOADPC) // used by cold-reset
k_write_pc <= 1;
case (dec_o_p1_mode)
`INDEXED: // address loaded, load argument
@@ -1050,25 +1055,25 @@
end
`SEQ_MEM_WRITE_L_1:
begin
- k_write_post_incdec <= dec_o_ea_wpost;
+ k_write_post_incdec <= dec_o_ea_wpost & (dec_o_p1_mode == `INDEXED);
state <= next_mem_state;
end
-
+
endcase
end
end
-
+
initial
begin
k_mem_state = 0;
k_cpu_oe = 0;
k_cpu_we = 0;
- k_new_pc = 16'hffff;
- k_write_tfr = 0;
- k_write_exg = 0;
+ k_new_pc = 16'hffff;
+ k_write_tfr = 0;
+ k_write_exg = 0;
k_mul_cnt = 0;
k_write_dest = 0;
k_indirect_loaded = 0;
end
endmodule
-
+
\ No newline at end of file
/* 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_postbyte has been loaded for page 2 or page 3 */ |
|
|
reg [2:0] k_mem_state; /* Memory mini-state machine */ |
|
/verilog/Changelog.txt
1,6 → 1,15
Changelong |
---------- |
|
25.10.14 |
-------- |
- decoders.v : removed unused signals |
- MC6809_cpu.v : Removed unused signals |
|
20.10.14 |
--------- |
- MC6809_cpu.v : fixed wrong postincrement/predecrement write-back after memory access |
|
25.07.14 |
--------- |
- decoders.v : new decoder: fix decoding of ABX, TST |
/verilog/alu16.v
151,8 → 151,8
always @(*) |
begin |
case (opcode_in) |
2'b00, 2'b10: overflow_out = (a_in[15] & b_in[15] & (~q_out[15])) | ((~a_in[15]) & (~b_in[15]) & q_out[7]); |
2'b01, 2'b11: overflow_out = (a_in[15] & (~b_in[15]) & (~q_out[15])) | ((~a_in[15]) & b_in[15] & q_out[7]); |
2'b00, 2'b10: overflow_out = (a_in[15] & b_in[15] & (~q_out[15])) | ((~a_in[15]) & (~b_in[15]) & q_out[15]); |
2'b01, 2'b11: overflow_out = (a_in[15] & (~b_in[15]) & (~q_out[15])) | ((~a_in[15]) & b_in[15] & q_out[15]); |
endcase |
end |
|
/verilog/decoders.v
1,12 → 1,11
|
/* |
* Signals which registers have to be read/written for the current opcode |
* Decodes an opcode |
* |
* All decoders in one module |
* |
* |
*/ |
`include "defs.v" |
|
|
module decoders( |
input wire clk_in, |
input wire [7:0] opcode, |
13,10 → 12,7
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 wire [3:0] path_left_addr_o, |
output wire [3:0] path_right_addr_o, |
output wire [3:0] dest_reg_o, |
|
output reg [3:0] path_left_addr_lo, |
output reg [3:0] path_right_addr_lo, |
output reg [3:0] dest_reg_lo, |
31,7 → 27,7
output reg [1:0] dest_memtype_lo, |
output wire operand_read_o, // reads 1 operand from memory |
output wire operand_write_o, // writes result to memory |
|
|
output wire [2:0] mode, |
output reg op_SYNC, |
output reg op_EXG, |
47,17 → 43,17
output reg op_JMP, |
output reg op_JSR, |
output wire use_s, |
|
|
output wire [4:0] alu_opcode, |
output wire dest_flags_o |
|
|
|
|
); |
reg [3:0] lr, rr, dr; |
reg [1:0] lm, rm, dm; |
reg ss, sz, p2, p3; |
reg [2:0] mo; |
reg [4:0] aop; |
reg [3:0] lr, rr, dr; // left, right and destination register addresses |
reg [1:0] lm, rm, dm; // left, right and destination memory sizes |
reg ss, sz, p2, p3; // S or *U, 16 or *8, page 2, page 3 |
reg [2:0] mo; // Addressing Mode |
reg [4:0] aop; // ALU opcode |
assign write_dest = (dr != `RN_INV); |
assign source_size = (lr < `RN_ACCA) | sz | (rm == `MT_WORD); |
// result size is used to determine the size of the argument |
65,13 → 61,9
// why do we need the result size ?... because of tfr&exg |
assign result_size = (dr == `RN_INV) ? (lr < `RN_ACCA): |
(dr < `RN_ACCA) ? 1:0; |
|
assign path_right_addr_o = rr; |
assign path_left_addr_o = lr; |
assign dest_reg_o = dr; |
|
// for registers, memory writes are handled differently |
|
|
assign operand_read_o = (lm != `MT_NONE) | (rm != `MT_NONE); |
assign operand_write_o = dm != `MT_NONE; |
assign path_left_memtype_o = lm; |
81,7 → 73,7
assign use_s = ss; |
assign mode = mo; |
assign alu_opcode = aop; |
|
|
always @(*) |
begin |
lr = `RN_INV; |
417,7 → 409,7
4'he: begin rm = `MT_WORD; dr = `RN_U; aop = `LD; end |
4'hf: begin lr = `RN_U; dm = `MT_WORD; aop = `ST; end |
endcase |
|
|
end |
4'he: |
begin |
440,7 → 432,7
4'he: begin rm = `MT_WORD; dr = `RN_U; aop = `LD; end |
4'hf: begin lr = `RN_U; dm = `MT_WORD; aop = `ST; end |
endcase |
|
|
end |
4'hf: |
begin |
729,7 → 721,7
endcase |
end |
endcase |
|
|
end |
always @(posedge clk_in) |
begin |
740,9 → 732,9
path_left_memtype_lo <= lm; |
dest_memtype_lo <= dm; |
end |
|
|
endmodule |
|
|
module decode_ea( |
input wire [7:0] eapostbyte, |
output reg [3:0] eabase_o, // base register |
753,9 → 745,9
output wire ea_is_indirect_o, |
output reg ea_write_back_o |
); |
|
|
assign ea_is_indirect_o = eapostbyte[7] & eapostbyte[4]; |
|
|
always @(*) |
begin |
eabase_o = `RN_PC; |
769,7 → 761,7
8'bx11_x_xxxx: eabase_o = `RN_S; |
endcase |
end |
|
|
always @(*) |
begin |
ea_ofs5_o = 1'b0; |
803,8 → 795,8
endcase |
end |
endmodule |
|
|
|
|
/* decodes the condition and checks the flags to see if it is met */ |
module test_condition( |
input wire [7:0] opcode, |
813,14 → 805,14
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) || |
(op == 8'h0e) || (op == 8'h6e) || (op == 8'h7e)) // jmp |
if ((opcode == 8'h16) || (opcode == 8'h17) || (opcode == 8'h8D) || |
(opcode == 8'h0e) || (opcode == 8'h6e) || (opcode == 8'h7e)) // jmp |
cond_taken = 1'b1; // LBRA/LBSR, BSR |
if (op[7:4] == 4'h2) |
case (op[3:0]) |
842,5 → 834,5
4'hf: cond_taken = (`DFLAGN != `DFLAGV) | (`DFLAGZ); // BLE |
endcase |
end |
|
|
endmodule |