From 1f91448ff1d205d1ecd8b695065043f6d54c8821 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Sat, 18 Jan 2020 21:33:56 +0100 Subject: [PATCH 1/2] MC6809: add Greg Miller's original version --- common/CPU/MC6809/mc6809.v | 147 +- common/CPU/MC6809/mc6809i.v | 4156 +++++++++++++++++++++++++++++++++++ 2 files changed, 4225 insertions(+), 78 deletions(-) create mode 100644 common/CPU/MC6809/mc6809i.v diff --git a/common/CPU/MC6809/mc6809.v b/common/CPU/MC6809/mc6809.v index 338e9557..b19d1552 100644 --- a/common/CPU/MC6809/mc6809.v +++ b/common/CPU/MC6809/mc6809.v @@ -1,89 +1,80 @@ `timescale 1ns / 1ps -module mc6809 -( - input CLK, - input CLKEN, - input nRESET, +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 08:11:34 09/23/2016 +// Design Name: +// Module Name: mc6809e +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module mc6809( + input [7:0] D, + output [7:0] DOut, + output [15:0] ADDR, + output RnW, + output E, + output Q, + output BS, + output BA, + input nIRQ, + input nFIRQ, + input nNMI, + input EXTAL, + input XTAL, + input nHALT, + input nRESET, + input MRDY, + input nDMABREQ + + , output [111:0] RegData - input CPU, + ); - output reg E, - output reg riseE, - output reg fallE, // everything except interrupts/dma registered/latched here +reg [1:0] clk_phase=2'b00; - output reg Q, - output reg riseQ, - output reg fallQ, // NMI,IRQ,FIRQ,DMA,HALT registered here +wire CLK; +assign CLK=EXTAL; - input [7:0] Din, - output [7:0] Dout, - output [15:0] ADDR, - output RnW, +wire LIC; +wire BUSY; +wire AVMA; +reg rE; +reg rQ; +assign E = rE; +assign Q = rQ; - input nIRQ, - input nFIRQ, - input nNMI, - input nHALT -); +mc6809i cpucore(.D(D), .DOut(DOut), .ADDR(ADDR), .RnW(RnW), .E(E), .Q(Q), .BS(BS), .BA(BA), .nIRQ(nIRQ), .nFIRQ(nFIRQ), + .nNMI(nNMI), .AVMA(AVMA), .BUSY(BUSY), .LIC(LIC), .nHALT(nHALT), .nRESET(nRESET), .nDMABREQ(nDMABREQ) + ,.RegData(RegData) + ); -cpu09 cpu1 -( - .clk(CLK), - .ce(fallE), - .rst(~nRESET | CPU), - .addr(ADDR1), - .rw(RnW1), - .data_out(Dout1), - .data_in(Din), - .irq(~nIRQ), - .firq(~nFIRQ), - .nmi(~nNMI), - .halt(~nHALT) -); - -mc6809is cpu2 -( - .CLK(CLK), - .D(Din), - .DOut(Dout2), - .ADDR(ADDR2), - .RnW(RnW2), - .fallE_en(fallE), - .fallQ_en(fallQ), - .nIRQ(nIRQ), - .nFIRQ(nFIRQ), - .nNMI(nNMI), - .nHALT(nHALT), - .nRESET(nRESET & CPU), - .nDMABREQ(1) -); - -wire [7:0] Dout1,Dout2; -wire [15:0] ADDR1,ADDR2; -wire RnW1,RnW2; - -assign Dout = CPU ? Dout2 : Dout1; -assign ADDR = CPU ? ADDR2 : ADDR1; -assign RnW = CPU ? RnW2 : RnW1; - -always @(posedge CLK) +always @(negedge CLK) begin - reg [1:0] clk_phase =0; - - fallE <= 0; - fallQ <= 0; - riseE <= 0; - riseQ <= 0; - - if (CLKEN) begin - clk_phase <= clk_phase + 1'd1; - case (clk_phase) - 2'b00: begin E <= 0; fallE <= 1; end - 2'b01: begin Q <= 1; riseQ <= 1; end - 2'b10: begin E <= 1; riseE <= 1; end - 2'b11: begin Q <= 0; fallQ <= 1; end - endcase - end + case (clk_phase) + 2'b00: + rE <= 0; + 2'b01: + rQ <= 1; + 2'b10: + rE <= 1; + 2'b11: + rQ <= 0; + endcase + + if (MRDY == 1'b1) + clk_phase <= clk_phase + 2'b01; end + endmodule diff --git a/common/CPU/MC6809/mc6809i.v b/common/CPU/MC6809/mc6809i.v new file mode 100644 index 00000000..5725aab4 --- /dev/null +++ b/common/CPU/MC6809/mc6809i.v @@ -0,0 +1,4156 @@ +`timescale 1ns / 1ns +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: Greg Miller +// Copyright (c) 2016, Greg Miller +// +// Create Date: 14:26:59 08/13/2016 +// Design Name: +// Module Name: mc6809 +// Project Name: Cycle-Accurate 6809 Core +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: Intended to be standalone Vanilla Verilog. +// +// Revision: +// Revision 1.0 - Initial Release +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + + +// +// The 6809 has incomplete instruction decoding. A collection of instructions, if met, end up actually behaving like +// a binary-adjacent neighbor. +// +// The soft core permits three different behaviors for this situation, controlled by the instantiation parameter +// ILLEGAL_INSTRUCTIONS +// +// "GHOST" - Mimic the 6809's incomplete decoding. This is as similar to a hard 6809 as is practical. [DEFAULT] +// +// "STOP" - Cause the soft core to cease execution, placing $DEAD on the address bus and R/W to 'read'. Interrupts, +// bus control (/HALT, /DMABREQ), etc. are ignored. The core intentionally seizes in this instance. +// (Frankly, this is useful when making changes to the core and you have a logic analyzer connected.) +// +// "IGNORE"- Cause the soft core to merely ignore illegal instructions. It will consider them 1-byte instructions and +// attempt to fetch and run an exception 1 byte later. +// + +module mc6809i +#( + parameter ILLEGAL_INSTRUCTIONS="GHOST" +) +( + + input [7:0] D, + output [7:0] DOut, + output [15:0] ADDR, + output RnW, + input E, + input Q, + output BS, + output BA, + input nIRQ, + input nFIRQ, + input nNMI, + output AVMA, + output BUSY, + output LIC, + input nHALT, + input nRESET, + input nDMABREQ, + output [111:0] RegData +); + +reg [7:0] DOutput; + +assign DOut = DOutput; + +reg RnWOut; // Combinatorial + +reg rLIC; +assign LIC = rLIC; + +reg rAVMA; +assign AVMA = rAVMA; + +reg rBUSY; +assign BUSY = rBUSY; + +// Bus control +// BS BA +// 0 0 normal (CPU running, CPU is master) +// 0 1 Interrupt Ack +// 1 0 Sync Ack +// 1 1 CPU has gone high-Z on A, D, R/W +// + +assign RnW = RnWOut; + + +///////////////////////////////////////////////// +// Vectors +`define RESET_VECTOR 16'HFFFE +`define NMI_VECTOR 16'HFFFC +`define SWI_VECTOR 16'HFFFA +`define IRQ_VECTOR 16'HFFF8 +`define FIRQ_VECTOR 16'HFFF6 +`define SWI2_VECTOR 16'HFFF4 +`define SWI3_VECTOR 16'HFFF2 +`define Reserved_VECTOR 16'HFFF0 + +////////////////////////////////////////////////////// +// Latched registers +// + +// The last-latched copy. +reg [7:0] a; +reg [7:0] b; +reg [15:0] x; +reg [15:0] y; +reg [15:0] u; +reg [15:0] s; +reg [15:0] pc; +reg [7:0] dp; +reg [7:0] cc; +reg [15:0] tmp; +reg [15:0] addr; +reg [15:0] ea; + + +// Debug ability to export register contents +assign RegData[7:0] = a; +assign RegData[15:8] = b; +assign RegData[31:16] = x; +assign RegData[47:32] = y; +assign RegData[63:48] = s; +assign RegData[79:64] = u; +assign RegData[87:80] = cc; +assign RegData[95:88] = dp; +assign RegData[111:96] = pc; + + + +// The values as being calculated +reg [7:0] a_nxt; +reg [7:0] b_nxt; +reg [15:0] x_nxt; +reg [15:0] y_nxt; +reg [15:0] u_nxt; +reg [15:0] s_nxt; +reg [15:0] pc_nxt; +reg [7:0] dp_nxt; +reg [7:0] cc_nxt; +reg [15:0] addr_nxt; +reg [15:0] ea_nxt; +reg [15:0] tmp_nxt; + +reg BS_nxt; +reg BA_nxt; + +// for ADDR, BS/BA, assign them to the flops +assign BS = BS_nxt; +assign BA = BA_nxt; +assign ADDR=addr_nxt; + +localparam CC_E= 8'H80; +localparam CC_F= 8'H40; +localparam CC_H= 8'H20; +localparam CC_I= 8'H10; +localparam CC_N= 8'H08; +localparam CC_Z= 8'H04; +localparam CC_V= 8'H02; +localparam CC_C= 8'H01; + +localparam CC_E_BIT= 3'd7; +localparam CC_F_BIT= 3'd6; +localparam CC_H_BIT= 3'd5; +localparam CC_I_BIT= 3'd4; +localparam CC_N_BIT= 3'd3; +localparam CC_Z_BIT= 3'd2; +localparam CC_V_BIT= 3'd1; +localparam CC_C_BIT= 3'd0; + +// Convenience calculations +reg [15:0] pc_p1; +reg [15:0] pc_p2; +reg [15:0] pc_p3; +reg [15:0] s_p1; +reg [15:0] s_m1; +reg [15:0] u_p1; +reg [15:0] u_m1; +reg [15:0] addr_p1; +reg [15:0] ea_p1; + +////////////////////////////////////////////////////// +// NMI Mask +// +// NMI is supposed to be masked - despite the name - until the 6809 loads a value into S. +// Frankly, I'm cheating slightly. If someone does a LDS #$0, it won't disable the mask. Pretty much anything else +// that changes the value of S from the default (which is currently $0) will clear the mask. A reset will set the mask again. +reg NMIMask; + +reg NMILatched; +reg NMISample; +reg NMISample2; +reg NMIClear; +reg NMIClear_nxt; +wire wNMIClear = NMIClear; + +reg IRQLatched; + +reg IRQSample; +reg IRQSample2; +reg FIRQLatched; +reg FIRQSample; +reg FIRQSample2; +reg HALTLatched; +reg HALTSample; +reg HALTSample2; +reg DMABREQLatched; +reg DMABREQSample; +reg DMABREQSample2; + +// Interrupt types +localparam INTTYPE_NMI = 3'H0 ; +localparam INTTYPE_IRQ = 3'H1 ; +localparam INTTYPE_FIRQ = 3'H2 ; +localparam INTTYPE_SWI = 3'H3 ; +localparam INTTYPE_SWI2 = 3'H4 ; +localparam INTTYPE_SWI3 = 3'H5 ; + +reg [2:0] IntType; +reg [2:0] IntType_nxt; + +////////////////////////////////////////////////////// +// Instruction Fetch Details +// +reg InstPage2; +reg InstPage3; +reg InstPage2_nxt; +reg InstPage3_nxt; + +reg [7:0] Inst1; +reg [7:0] Inst2; +reg [7:0] Inst3; +reg [7:0] Inst1_nxt; +reg [7:0] Inst2_nxt; +reg [7:0] Inst3_nxt; + + +localparam CPUSTATE_RESET = 7'd0; +localparam CPUSTATE_RESET0 = 7'd1; + +localparam CPUSTATE_RESET2 = 7'd3; +localparam CPUSTATE_FETCH_I1 = 7'd4; +localparam CPUSTATE_FETCH_I1V2 = 7'd5; +localparam CPUSTATE_FETCH_I2 = 7'd8; + +localparam CPUSTATE_LBRA_OFFSETLOW = 7'd17; +localparam CPUSTATE_LBRA_DONTCARE = 7'd18; +localparam CPUSTATE_LBRA_DONTCARE2 = 7'd19; + + + +localparam CPUSTATE_BRA_DONTCARE = 7'd20; + +localparam CPUSTATE_BSR_DONTCARE1 = 7'd21; +localparam CPUSTATE_BSR_DONTCARE2 = 7'd22; +localparam CPUSTATE_BSR_RETURNLOW = 7'd23; +localparam CPUSTATE_BSR_RETURNHIGH = 7'd24; + +localparam CPUSTATE_TFR_DONTCARE1 = 7'd26; +localparam CPUSTATE_TFR_DONTCARE2 = 7'd27; +localparam CPUSTATE_TFR_DONTCARE3 = 7'd28; +localparam CPUSTATE_TFR_DONTCARE4 = 7'd29; + +localparam CPUSTATE_EXG_DONTCARE1 = 7'd30; +localparam CPUSTATE_EXG_DONTCARE2 = 7'd31; +localparam CPUSTATE_EXG_DONTCARE3 = 7'd32; +localparam CPUSTATE_EXG_DONTCARE4 = 7'd33; +localparam CPUSTATE_EXG_DONTCARE5 = 7'd34; +localparam CPUSTATE_EXG_DONTCARE6 = 7'd35; + +localparam CPUSTATE_ABX_DONTCARE = 7'd36; + +localparam CPUSTATE_RTS_HI = 7'd38; +localparam CPUSTATE_RTS_LO = 7'd39; +localparam CPUSTATE_RTS_DONTCARE2 = 7'd40; + +localparam CPUSTATE_16IMM_LO = 7'd41; +localparam CPUSTATE_ALU16_DONTCARE = 7'd42; +localparam CPUSTATE_DIRECT_DONTCARE = 7'd43; + +localparam CPUSTATE_ALU_EA = 7'd44; + +localparam CPUSTATE_ALU_DONTCARE = 7'd46; +localparam CPUSTATE_ALU_WRITEBACK = 7'd47; + +localparam CPUSTATE_LD16_LO = 7'd48; + +localparam CPUSTATE_ST16_LO = 7'd49; +localparam CPUSTATE_ALU16_LO = 7'd50; + + + + +localparam CPUSTATE_JSR_DONTCARE = 7'd53; +localparam CPUSTATE_JSR_RETLO = 7'd54; +localparam CPUSTATE_JSR_RETHI = 7'd55; +localparam CPUSTATE_EXTENDED_ADDRLO = 7'd56; +localparam CPUSTATE_EXTENDED_DONTCARE = 7'd57; +localparam CPUSTATE_INDEXED_BASE = 7'd58; + + +localparam CPUSTATE_IDX_DONTCARE3 = 7'd60; + +localparam CPUSTATE_IDX_OFFSET_LO = 7'd61; +localparam CPUSTATE_IDX_16OFFSET_LO = 7'd62; + +localparam CPUSTATE_IDX_16OFF_DONTCARE0= 7'd63; +localparam CPUSTATE_IDX_16OFF_DONTCARE1= 7'd64; +localparam CPUSTATE_IDX_16OFF_DONTCARE2= 7'd65; +localparam CPUSTATE_IDX_16OFF_DONTCARE3= 7'd66; + +localparam CPUSTATE_IDX_DOFF_DONTCARE1 = 7'd68; +localparam CPUSTATE_IDX_DOFF_DONTCARE2 = 7'd69; +localparam CPUSTATE_IDX_DOFF_DONTCARE3 = 7'd70; +localparam CPUSTATE_IDX_PC16OFF_DONTCARE = 7'd71; + +localparam CPUSTATE_IDX_EXTIND_LO = 7'd72; +localparam CPUSTATE_IDX_EXTIND_DONTCARE = 7'd73; + +localparam CPUSTATE_INDIRECT_HI = 7'd74; +localparam CPUSTATE_INDIRECT_LO = 7'd75; +localparam CPUSTATE_INDIRECT_DONTCARE = 7'd76; +localparam CPUSTATE_MUL_ACTION = 7'd77; + +localparam CPUSTATE_PSH_DONTCARE1 = 7'd80; +localparam CPUSTATE_PSH_DONTCARE2 = 7'd81; +localparam CPUSTATE_PSH_DONTCARE3 = 7'd82; +localparam CPUSTATE_PSH_ACTION = 7'd83; + +localparam CPUSTATE_PUL_DONTCARE1 = 7'd84; +localparam CPUSTATE_PUL_DONTCARE2 = 7'd85; +localparam CPUSTATE_PUL_ACTION = 7'd86; + +localparam CPUSTATE_NMI_START = 7'd87; +localparam CPUSTATE_IRQ_DONTCARE = 7'd88; +localparam CPUSTATE_IRQ_START = 7'd89; +localparam CPUSTATE_IRQ_DONTCARE2 = 7'd90; +localparam CPUSTATE_IRQ_VECTOR_HI = 7'd91; +localparam CPUSTATE_IRQ_VECTOR_LO = 7'd92; +localparam CPUSTATE_FIRQ_START = 7'd93; +localparam CPUSTATE_CC_DONTCARE = 7'd94; +localparam CPUSTATE_SWI_START = 7'd95; + +localparam CPUSTATE_TST_DONTCARE1 = 7'd96; +localparam CPUSTATE_TST_DONTCARE2 = 7'd97; + +localparam CPUSTATE_DEBUG = 7'd98; + +localparam CPUSTATE_16IMM_DONTCARE = 7'd99; + +localparam CPUSTATE_HALTED = 7'd100; + +localparam CPUSTATE_HALT_EXIT2 = 7'd102; +localparam CPUSTATE_STOP = 7'd105; +localparam CPUSTATE_STOP2 = 7'd106; +localparam CPUSTATE_STOP3 = 7'd107; + + +localparam CPUSTATE_CWAI = 7'd108; +localparam CPUSTATE_CWAI_DONTCARE1 = 7'd109; +localparam CPUSTATE_CWAI_POST = 7'd110; + +localparam CPUSTATE_DMABREQ = 7'd111; +localparam CPUSTATE_DMABREQ_EXIT = 7'd112; +localparam CPUSTATE_SYNC = 7'd113; +localparam CPUSTATE_SYNC_EXIT = 7'd114; + +localparam CPUSTATE_INT_DONTCARE = 7'd115; + + +reg [6:0] CpuState = CPUSTATE_RESET; +reg [6:0] CpuState_nxt = CPUSTATE_RESET; + +reg [6:0] NextState = CPUSTATE_RESET; +reg [6:0] NextState_nxt = CPUSTATE_RESET; + +wire [6:0] PostIllegalState; + +// If we encounter something like an illegal addressing mode (an index mode that's illegal for instance) +// What state should we go to? +generate +if (ILLEGAL_INSTRUCTIONS=="STOP") +begin : postillegal + assign PostIllegalState = CPUSTATE_STOP; +end +else +begin + assign PostIllegalState = CPUSTATE_FETCH_I1; +end +endgenerate + + + +/////////////////////////////////////////////////////////////////////// + +// +// MapInstruction - Considering how the core was instantiated, this +// will either directly return D[7:0] *or* remap values from D[7:0] +// that relate to undefined instructions in the 6809 to the instructions +// that the 6809 actually executed when these were encountered, due to +// incomplete decoding. +// +// NEG, COM, LSR, DEC - these four instructions, in Direct, Inherent (A or B) +// Indexed, or Extended addressing do not actually decode bit 0 on the instruction. +// Thus, for instance, a $51 encountered will be executed as a $50, which is a NEGB. +// + +// Specifically, the input is an instruction; if it matches an unknown instruction that the +// 6809 is known to ghost to another instruction, the output of the function +// is the the instruction that actually gets executed. Otherwise, the output is the +// input. + +function [7:0] MapInstruction(input [7:0] i); +reg [3:0] topnyb; +reg [3:0] btmnyb; +reg [7:0] newinst; +begin + newinst = i; + + topnyb = i[7:4]; + btmnyb = i[3:0]; + + if ( (topnyb == 4'H0) || + (topnyb == 4'H4) || + (topnyb == 4'H5) || + (topnyb == 4'H6) || + (topnyb == 4'H7) + ) + begin + if (btmnyb == 4'H1) + newinst = {topnyb, 4'H0}; + if (btmnyb == 4'H2) + newinst = {topnyb, 4'H3}; + if (btmnyb == 4'H5) + newinst = {topnyb, 4'H4}; + if (btmnyb == 4'HB) + newinst = {topnyb, 4'HA}; + end + MapInstruction = newinst; +end +endfunction + + +wire [7:0] MappedInstruction; +generate +if (ILLEGAL_INSTRUCTIONS=="GHOST") +begin : ghost + assign MappedInstruction = MapInstruction(D); +end +else +begin + assign MappedInstruction = D; +end +endgenerate + + + +/////////////////////////////////////////////////////////////////////// + +function IllegalInstruction(input [7:0] i); +reg [3:0] hi; +reg [3:0] lo; +reg illegal; +begin + illegal = 1'b0; + hi = i[7:4]; + lo = i[3:0]; + if ( (hi == 4'H0) || (hi == 4'H4) || (hi == 4'H5) || (hi == 4'H6) || (hi == 4'H7) ) + begin + if ( (lo == 4'H1) || (lo == 4'H2) || (lo == 4'H5) || (lo == 4'HB) ) + illegal = 1'b1; + if (lo == 4'HE) + if ( (hi == 4'H4) || (hi == 4'H5) ) + illegal = 1'b1; + end + if (hi == 4'H3) + begin + if ( (lo == 4'H8) || (lo == 4'HE) ) + illegal = 1'b1; + end + if (hi == 4'H1) + begin + if ( (lo == 4'H4) || (lo == 4'H5) || (lo == 4'H8) || (lo == 4'HB) ) + illegal = 1'b1; + end + if ( (hi == 4'H8) || (hi == 4'HC) ) + begin + if ( (lo == 4'H7) || (lo == 4'HF) ) + illegal = 1'b1; + if ( lo == 4'HD ) + if (hi == 4'HC) + illegal = 1'b1; + end + IllegalInstruction = illegal; +end +endfunction + +wire IsIllegalInstruction; + +generate +if (ILLEGAL_INSTRUCTIONS=="GHOST") +begin : never_illegal + assign IsIllegalInstruction = 1'b0; +end +else +begin + assign IsIllegalInstruction = IllegalInstruction(Inst1); +end +endgenerate + +wire [6:0] IllegalInstructionState; +generate +if (ILLEGAL_INSTRUCTIONS=="IGNORE") +begin : illegal_state + assign IllegalInstructionState = CPUSTATE_FETCH_I1; +end +else if (ILLEGAL_INSTRUCTIONS=="STOP") +begin + assign IllegalInstructionState = CPUSTATE_STOP; +end +else +begin + assign IllegalInstructionState = 7'd0; +end +endgenerate + + +/////////////////////////////////////////////////////////////////////// + + +always @(negedge NMISample2 or posedge wNMIClear) +begin + if (wNMIClear == 1) + NMILatched <= 1; + else if (NMIMask == 0) + NMILatched <= 0; + else + NMILatched <= 1; +end + +// +// The 6809 specs say that the CPU control signals are sampled on the falling edge of Q. +// It also says that the interrupts require 1 cycle of synchronization time. +// That's vague, as it doesn't say where "1 cycle" starts or ends. Starting from the +// falling edge of Q, the next cycle notices an assertion. From checking a hard 6809 on +// an analyzer, what they really mean is that it's sampled on the falling edge of Q, +// but there's a one cycle delay from the falling edge of E (0.25 clocks from the falling edge of Q +// where the signals were sampled) before it can be noticed. +// So, SIGNALSample is the latched value at the falling edge of Q +// SIGNALSample2 is the latched value at the falling edge of E (0.25 clocks after the line above) +// SIGNALLatched is the latched value at the falling edge of E (1 cycle after the line above) +// +// /HALT and /DMABREQ are delayed one cycle less than interrupts. The 6809 specs infer these details, +// but don't list the point-of-reference they're written from (for instance, they say that an interrupt requires +// a cycle for synchronization; however, it isn't clear whether that's from the falling Q to the next falling Q, +// a complete intermediate cycle, the falling E to the next falling E, etc.) - which, in the end, required an +// analyzer on the 6809 to determine how many cycles before a new instruction an interrupt (or /HALT & /DMABREQ) +// had to be asserted to be noted instead of the next instruction running start to finish. +// +always @(negedge Q) +begin + NMISample <= nNMI; + + IRQSample <= nIRQ; + + FIRQSample <= nFIRQ; + + HALTSample <= nHALT; + + DMABREQSample <= nDMABREQ; + + +end + + +reg rnRESET=0; // The latched version of /RESET, useful 1 clock after it's latched +always @(negedge E) +begin + rnRESET <= nRESET; + + NMISample2 <= NMISample; + + IRQSample2 <= IRQSample; + IRQLatched <= IRQSample2; + + FIRQSample2 <= FIRQSample; + FIRQLatched <= FIRQSample2; + + HALTSample2 <= HALTSample; + HALTLatched <= HALTSample2; + + DMABREQSample2 <= DMABREQSample; + DMABREQLatched <= DMABREQSample2; + + + if (rnRESET == 1) + begin + CpuState <= CpuState_nxt; + + // Don't interpret this next item as "The Next State"; it's a special case 'after this + // generic state, go to this programmable state', so that a single state + // can be shared for many tasks. [Specifically, the stack push/pull code, which is used + // for PSH, PUL, Interrupts, RTI, etc. + NextState <= NextState_nxt; + + // CPU registers latch from the combinatorial circuit + a <= a_nxt; + b <= b_nxt; + x <= x_nxt; + y <= y_nxt; + s <= s_nxt; + u <= u_nxt; + cc <= cc_nxt; + dp <= dp_nxt; + pc <= pc_nxt; + tmp <= tmp_nxt; + addr <= addr_nxt; + ea <= ea_nxt; + + InstPage2 <= InstPage2_nxt; + InstPage3 <= InstPage3_nxt; + Inst1 <= Inst1_nxt; + Inst2 <= Inst2_nxt; + Inst3 <= Inst3_nxt; + NMIClear <= NMIClear_nxt; + + IntType <= IntType_nxt; + + if (s != s_nxt) // Once S changes at all (default is '0'), release the NMI Mask. + NMIMask <= 1'b0; + end + else + begin + CpuState <= CPUSTATE_RESET; + NMIMask <= 1'b1; // Mask NMI until S is loaded. + NMIClear <= 1'b0; // Mark us as not having serviced NMI + end +end + + +///////////////////////////////////////////////////////////////// +// Decode the Index byte + +localparam IDX_REG_X = 3'd0; +localparam IDX_REG_Y = 3'd1; +localparam IDX_REG_U = 3'd2; +localparam IDX_REG_S = 3'd3; +localparam IDX_REG_PC = 3'd4; + +localparam IDX_MODE_POSTINC1 = 4'd0; +localparam IDX_MODE_POSTINC2 = 4'd1; +localparam IDX_MODE_PREDEC1 = 4'd2; +localparam IDX_MODE_PREDEC2 = 4'd3; +localparam IDX_MODE_NOOFFSET = 4'd4; +localparam IDX_MODE_B_OFFSET = 4'd5; +localparam IDX_MODE_A_OFFSET = 4'd6; +localparam IDX_MODE_5BIT_OFFSET= 4'd7; // Special case, not bit pattern 7; the offset sits in the bit pattern +localparam IDX_MODE_8BIT_OFFSET= 4'd8; +localparam IDX_MODE_16BIT_OFFSET = 4'd9; +localparam IDX_MODE_D_OFFSET = 4'd11; +localparam IDX_MODE_8BIT_OFFSET_PC = 4'd12; +localparam IDX_MODE_16BIT_OFFSET_PC= 4'd13; +localparam IDX_MODE_EXTENDED_INDIRECT = 4'd15; + +// Return: +// Register base [3 bits] +// Indirect [1 bit] +// Mode [4 bits] + +function [7:0] IndexDecode(input [7:0] postbyte); +reg [2:0] regnum; +reg indirect; +reg [3:0] mode; +begin + indirect = 0; + mode = 0; + + if (postbyte[7] == 0) // 5-bit + begin + mode = IDX_MODE_5BIT_OFFSET; + end + else + begin + mode = postbyte[3:0]; + indirect = postbyte[4]; + end + if ((mode != IDX_MODE_8BIT_OFFSET_PC) && (mode != IDX_MODE_16BIT_OFFSET_PC)) + regnum[2:0] = postbyte[6:5]; + else + regnum[2:0] = IDX_REG_PC; + + IndexDecode = {indirect, mode, regnum}; +end +endfunction + +wire [3:0] IndexedMode; +wire IndexedIndirect; +wire [2:0] IndexedRegister; + +assign {IndexedIndirect, IndexedMode, IndexedRegister} = IndexDecode(Inst2); + +///////////////////////////////////////////////////////////////// +// Is this a JMP instruction? (irrespective of addressing mode) +function IsJMP(input [7:0] inst); +reg [3:0] hi; +reg [3:0] lo; +begin + hi = inst[7:4]; + lo = inst[3:0]; + + IsJMP = 0; + if ((hi == 4'H0) || (hi == 4'H6) || (hi == 4'H7)) + if (lo == 4'HE) + IsJMP = 1; +end +endfunction + +/////////////////////////////////////////////////////////////////// +// Is this an 8-bit Store? + +localparam ST8_REG_A = 1'b0; +localparam ST8_REG_B = 1'b1; + +function [1:0] IsST8(input [7:0] inst); +reg regnum; +reg IsStore; +begin + + IsStore = 1'b0; + regnum = 1'b1; + + if ( (Inst1 == 8'H97) || (Inst1 == 8'HA7) || (Inst1 == 8'HB7) ) + begin + IsStore = 1'b1; + regnum = 1'b0; + end + else if ( (Inst1 == 8'HD7) || (Inst1 == 8'HE7) || (Inst1 == 8'HF7) ) + begin + IsStore = 1'b1; + regnum = 1'b1; + end + IsST8 = {IsStore, regnum}; +end +endfunction + +wire IsStore8; +wire Store8RegisterNum; + +assign {IsStore8, Store8RegisterNum} = IsST8(Inst1); + + +///////////////////////////////////////////////////////////////// +// Is this a 16-bit Store? + +localparam ST16_REG_X = 3'd0; +localparam ST16_REG_Y = 3'd1; +localparam ST16_REG_U = 3'd2; +localparam ST16_REG_S = 3'd3; +localparam ST16_REG_D = 3'd4; + + +function [3:0] IsST16(input [7:0] inst); +reg [3:0] hi; +reg [3:0] lo; +reg [2:0] regnum; +reg IsStore; +begin + hi = inst[7:4]; + lo = inst[3:0]; + IsStore = 1'b0; + regnum = 3'b111; + + if ((inst == 8'H9F) || (inst == 8'HAF) || (inst == 8'HBF)) + begin + IsStore = 1; + if (~InstPage2) + regnum = ST16_REG_X; + else + regnum = ST16_REG_Y; + end + else if ((inst == 8'HDF) || (inst == 8'HEF) || (inst == 8'HFF)) + begin + IsStore = 1; + if (~InstPage2) + regnum = ST16_REG_U; + else + regnum = ST16_REG_S; + end + else if ((inst == 8'HDD) || (inst == 8'HED) || (inst == 8'HFD)) + begin + IsStore = 1; + regnum = ST16_REG_D; + end + + IsST16 = {IsStore, regnum}; +end +endfunction + +wire IsStore16; +wire [2:0] StoreRegisterNum; + +assign {IsStore16, StoreRegisterNum} = IsST16(Inst1); + +///////////////////////////////////////////////////////////////// +// Is this a special Immediate mode instruction, ala +// PSH, PUL, EXG, TFR, ANDCC, ORCC +function IsSpecialImm(input [7:0] inst); +reg is; +reg [3:0] hi; +reg [3:0] lo; +begin + hi = inst[7:4]; + lo = inst[3:0]; + is = 0; + + if (hi == 4'H1) + begin + if ( (lo == 4'HA) || (lo == 4'HC) || (lo == 4'HE) || (lo == 4'HF) ) // ORCC, ANDCC, EXG, TFR + is = 1; + end + else if (hi == 4'H3) + begin + if ( (lo >= 4'H3) && (lo <= 4'H7) ) // PSHS, PULS, PSHU, PULU + is = 1; + end + else + is = 0; + + IsSpecialImm = is; +end +endfunction +wire IsSpecialImmediate = IsSpecialImm(Inst1); + +///////////////////////////////////////////////////////////////// +// Is this a one-byte instruction? [The 6809 reads 2 bytes for every instruction, minimum (it can read more). On a one-byte, we have to ensure that we haven't skipped the PC ahead. +function IsOneByteInstruction(input [7:0] inst); +reg is; +reg [3:0] hi; +reg [3:0] lo; +begin + hi = inst[7:4]; + lo = inst[3:0]; + is = 1'b0; + + if ( (hi == 4'H4) || (hi == 4'H5) ) + is = 1'b1; + else if ( hi == 4'H1) + begin + if ( (lo == 4'H2) || (lo == 4'H3) || (lo == 4'H9) || (lo == 4'HD) ) + is = 1'b1; + end + else if (hi == 4'H3) + begin + if ( (lo >= 4'H9) && (lo != 4'HC) ) + is = 1'b1; + end + else + is = 1'b0; + + IsOneByteInstruction = is; +end +endfunction + +///////////////////////////////////////////////////////////////// +// ALU16 - Simpler than the 8 bit ALU + +localparam ALU16_REG_X = 3'd0; +localparam ALU16_REG_Y = 3'd1; +localparam ALU16_REG_U = 3'd2; +localparam ALU16_REG_S = 3'd3; +localparam ALU16_REG_D = 3'd4; + +function [2:0] ALU16RegFromInst(input Page2, input Page3, input [7:0] inst); +reg [2:0] srcreg; +begin + srcreg = 3'b111; // default + casex ({Page2, Page3, inst}) // Note pattern for the matching below + 10'b1010xx0011: // 1083, 1093, 10A3, 10B3 CMPD + srcreg = ALU16_REG_D; + 10'b1010xx1100: // 108C, 109C, 10AC, 10BC CMPY + srcreg = ALU16_REG_Y; + 10'b0110xx0011: // 1183, 1193, 11A3, 11B3 CMPU + srcreg = ALU16_REG_U; + 10'b0110xx1100: // 118C, 119C, 11AC, 11BC CMPS + srcreg = ALU16_REG_S; + 10'b0010xx1100: // 8C,9C,AC,BC CMPX + srcreg = ALU16_REG_X; + + 10'b0011xx0011: // C3, D3, E3, F3 ADDD + srcreg = ALU16_REG_D; + + 10'b0011xx1100: // CC, DC, EC, FC LDD + srcreg = ALU16_REG_D; + 10'b0010xx1110: // 8E LDX, 9E LDX, AE LDX, BE LDX + srcreg = ALU16_REG_X; + 10'b0011xx1110: // CE LDU, DE LDU, EE LDU, FE LDU + srcreg = ALU16_REG_U; + 10'b1010xx1110: // 108E LDY, 109E LDY, 10AE LDY, 10BE LDY + srcreg = ALU16_REG_Y; + 10'b1011xx1110: // 10CE LDS, 10DE LDS, 10EE LDS, 10FE LDS + srcreg = ALU16_REG_S; + 10'b0010xx0011: // 83, 93, A3, B3 SUBD + srcreg = ALU16_REG_D; + + 10'H03A: // 3A ABX + srcreg = ALU16_REG_X; + 10'H030: // 30 LEAX + srcreg = ALU16_REG_X; + 10'H031: // 31 LEAY + srcreg = ALU16_REG_Y; + 10'H032: // 32 LEAS + srcreg = ALU16_REG_S; + 10'H033: // 32 LEAU + srcreg = ALU16_REG_U; + default: + srcreg = 3'b111; + endcase + ALU16RegFromInst = srcreg; +end +endfunction + +wire [2:0] ALU16Reg = ALU16RegFromInst(InstPage2, InstPage3, Inst1); + +localparam ALUOP16_SUB = 3'H0; +localparam ALUOP16_ADD = 3'H1; +localparam ALUOP16_LD = 3'H2; +localparam ALUOP16_CMP = 3'H3; +localparam ALUOP16_LEA = 3'H4; +localparam ALUOP16_INVALID = 3'H7; + +function [3:0] ALU16OpFromInst(input Page2, input Page3, input [7:0] inst); +reg [2:0] aluop; +reg writeback; +begin + aluop = 3'b111; + writeback = 1'b1; + casex ({Page2, Page3, inst}) + 10'b1010xx0011: // 1083, 1093, 10A3, 10B3 CMPD + begin + aluop = ALUOP16_CMP; + writeback = 1'b0; + end + 10'b1010xx1100: // 108C, 109C, 10AC, 10BC CMPY + begin + aluop = ALUOP16_CMP; + writeback = 1'b0; + end + 10'b0110xx0011: // 1183, 1193, 11A3, 11B3 CMPU + begin + aluop = ALUOP16_CMP; + writeback = 1'b0; + end + 10'b0110xx1100: // 118C, 119C, 11AC, 11BC CMPS + begin + aluop = ALUOP16_CMP; + writeback = 1'b0; + end + 10'b0010xx1100: // 8C,9C,AC,BC CMPX + begin + aluop = ALUOP16_CMP; + writeback = 1'b0; + end + + 10'b0011xx0011: // C3, D3, E3, F3 ADDD + aluop = ALUOP16_ADD; + + 10'b0011xx1100: // CC, DC, EC, FC LDD + aluop = ALUOP16_LD; + 10'b001xxx1110: // 8E LDX, 9E LDX, AE LDX, BE LDX, CE LDU, DE LDU, EE LDU, FE LDU + aluop = ALUOP16_LD; + 10'b101xxx1110: // 108E LDY, 109E LDY, 10AE LDY, 10BE LDY, 10CE LDS, 10DE LDS, 10EE LDS, 10FE LDS + aluop = ALUOP16_LD; + + 10'b0010xx0011: // 83, 93, A3, B3 SUBD + aluop = ALUOP16_SUB; + + 10'H03A: // 3A ABX + aluop = ALUOP16_ADD; + + 10'b00001100xx: // $30-$33, LEAX, LEAY, LEAS, LEAU + aluop = ALUOP16_LEA; + + default: + aluop = ALUOP16_INVALID; + endcase + ALU16OpFromInst = {writeback, aluop}; +end +endfunction + +wire ALU16OpWriteback; +wire [2:0] ALU16Opcode; + +assign {ALU16OpWriteback, ALU16Opcode} = ALU16OpFromInst(InstPage2, InstPage3, Inst1); + +wire IsALU16Opcode = (ALU16Opcode != 3'b111); + +function [23:0] ALU16Inst(input [2:0] operation16, input [15:0] a_arg, input [15:0] b_arg, input [7:0] cc_arg); +reg [7:0] cc_out; +reg [15:0] ALUFn; +reg carry; +reg borrow; +begin + cc_out = cc_arg; + case (operation16) + ALUOP16_ADD: + begin + {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} + b_arg; + cc_out[CC_V_BIT] = (a_arg[15] & b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & ~b_arg[15] & ALUFn[15]); + end + + ALUOP16_SUB: + begin + {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg}; + cc_out[CC_V_BIT] = (a_arg[15] & ~b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & b_arg[15] & ALUFn[15]); + end + + ALUOP16_LD: + begin + ALUFn = b_arg; + cc_out[CC_V_BIT] = 1'b0; + end + + ALUOP16_CMP: + begin + {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg}; + cc_out[CC_V_BIT] = (a_arg[15] & ~b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & b_arg[15] & ALUFn[15]); + end + + ALUOP16_LEA: + begin + ALUFn = a_arg; + end + + default: + ALUFn = 16'H0000; + + endcase + cc_out[CC_Z_BIT] = (ALUFn[15:0] == 16'H0000); + if (operation16 != ALUOP16_LEA) + cc_out[CC_N_BIT] = ALUFn[15]; + ALU16Inst = {cc_out, ALUFn}; +end +endfunction + +reg [2:0] ALU16_OP; +reg [15:0] ALU16_A; +reg [15:0] ALU16_B; +reg [7:0] ALU16_CC; + +// Top 8 bits == CC, bottom 8 bits = output value +wire [23:0] ALU16 = ALU16Inst(ALU16_OP, ALU16_A, ALU16_B, ALU16_CC); + + +///////////////////////////////////////////////////////////////// +// ALU + +// The ops are organized from the 4 low-order bits of the instructions for the first set of ops, then 16-31 are the second set - even though bit 4 isn't representative. +localparam ALUOP_NEG = 5'd0; +localparam ALUOP_COM = 5'd3; +localparam ALUOP_LSR = 5'd4; +localparam ALUOP_ROR = 5'd6; +localparam ALUOP_ASR = 5'd7; +localparam ALUOP_ASL = 5'd8; +localparam ALUOP_LSL = 5'd8; +localparam ALUOP_ROL = 5'd9; +localparam ALUOP_DEC = 5'd10; +localparam ALUOP_INC = 5'd12; +localparam ALUOP_TST = 5'd13; +localparam ALUOP_CLR = 5'd15; + +localparam ALUOP_SUB = 5'd16; +localparam ALUOP_CMP = 5'd17; +localparam ALUOP_SBC = 5'd18; +localparam ALUOP_AND = 5'd20; +localparam ALUOP_BIT = 5'd21; +localparam ALUOP_LD = 5'd22; +localparam ALUOP_EOR = 5'd24; +localparam ALUOP_ADC = 5'd25; +localparam ALUOP_OR = 5'd26; +localparam ALUOP_ADD = 5'd27; + +function [5:0] ALUOpFromInst(input [7:0] inst); +reg [4:0] op; +reg writeback; +begin + // Okay, this turned out to be simpler than I expected ... + op = {inst[7], inst[3:0]}; + case (op) + ALUOP_CMP: + writeback = 0; + ALUOP_TST: + writeback = 0; + ALUOP_BIT: + writeback = 0; + default: + writeback = 1; + endcase + ALUOpFromInst = {writeback, op}; +end +endfunction + +wire [4:0] ALU8Op; +wire ALU8Writeback; + +assign {ALU8Writeback, ALU8Op} = ALUOpFromInst(Inst1); + +reg [7:0] ALU_A; +reg [7:0] ALU_B; +reg [7:0] ALU_CC; +reg [4:0] ALU_OP; + + +function [15:0] ALUInst(input [4:0] operation, input [7:0] a_arg, input [7:0] b_arg, input [7:0] cc_arg); +reg [7:0] cc_out; +reg [7:0] ALUFn; +reg carry; +reg borrow; +begin + cc_out = cc_arg; + case (operation) + ALUOP_NEG: + begin + ALUFn[7:0] = ~a_arg + 1'b1; + cc_out[CC_C_BIT] = (ALUFn[7:0] != 8'H00); + cc_out[CC_V_BIT] = (a_arg == 8'H80); + end + + ALUOP_LSL: + begin + {cc_out[CC_C_BIT], ALUFn} = {a_arg, 1'b0}; + cc_out[CC_V_BIT] = a_arg[7] ^ a_arg[6]; + end + + ALUOP_LSR: + begin + {ALUFn, cc_out[CC_C_BIT]} = {1'b0, a_arg}; + end + + ALUOP_ASR: + begin + {ALUFn, cc_out[CC_C_BIT]} = {a_arg[7], a_arg}; + end + + ALUOP_ROL: + begin + {cc_out[CC_C_BIT], ALUFn} = {a_arg, cc_arg[CC_C_BIT]}; + cc_out[CC_V_BIT] = a_arg[7] ^ a_arg[6]; + end + + ALUOP_ROR: + begin + {ALUFn, cc_out[CC_C_BIT]} = {cc_arg[CC_C_BIT], a_arg}; + end + + ALUOP_OR: + begin + ALUFn[7:0] = (a_arg | b_arg); + cc_out[CC_V_BIT] = 1'b0; + end + + ALUOP_ADD: + begin + {cc_out[CC_C_BIT], ALUFn[7:0]} = {1'b0, a_arg} + {1'b0, b_arg}; + cc_out[CC_V_BIT] = (a_arg[7] & b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & ~b_arg[7] & ALUFn[7]); + cc_out[CC_H_BIT] = a_arg[4] ^ b_arg[4] ^ ALUFn[4]; + end + + ALUOP_SUB: + begin + {cc_out[CC_C_BIT], ALUFn[7:0]} = {1'b0, a_arg} - {1'b0, b_arg}; + cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]); + end + + ALUOP_AND: + begin + ALUFn[7:0] = (a_arg & b_arg); + cc_out[CC_V_BIT] = 1'b0; + end + + ALUOP_BIT: + begin + ALUFn[7:0] = (a_arg & b_arg); + cc_out[CC_V_BIT] = 1'b0; + end + + ALUOP_EOR: + begin + ALUFn[7:0] = (a_arg ^ b_arg); + cc_out[CC_V_BIT] = 1'b0; + end + + ALUOP_CMP: + begin + {cc_out[CC_C_BIT], ALUFn[7:0]} = {1'b0, a_arg} - {1'b0, b_arg}; + cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]); + end + + ALUOP_COM: + begin + ALUFn[7:0] = ~a_arg; + cc_out[CC_V_BIT] = 1'b0; + cc_out[CC_C_BIT] = 1'b1; + end + + ALUOP_ADC: + begin + {cc_out[CC_C_BIT], ALUFn[7:0]} = {1'b0, a_arg} + {1'b0, b_arg} + cc_arg[CC_C_BIT]; + cc_out[CC_V_BIT] = (a_arg[7] & b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & ~b_arg[7] & ALUFn[7]); + cc_out[CC_H_BIT] = a_arg[4] ^ b_arg[4] ^ ALUFn[4]; + end + + ALUOP_LD: + begin + ALUFn[7:0] = b_arg; + cc_out[CC_V_BIT] = 1'b0; + end + + ALUOP_INC: + begin + {carry, ALUFn} = {1'b0, a_arg} + 1'b1; + cc_out[CC_V_BIT] = (~a_arg[7] & ALUFn[7]); + end + + ALUOP_DEC: + begin + {carry, ALUFn[7:0]} = {1'b0, a_arg} - 1'b1; + cc_out[CC_V_BIT] = (a_arg[7] & ~ALUFn[7]); + end + + ALUOP_CLR: + begin + ALUFn[7:0] = 8'H00; + cc_out[CC_V_BIT] = 1'b0; + cc_out[CC_C_BIT] = 1'b0; + end + + ALUOP_TST: + begin + ALUFn[7:0] = a_arg; + cc_out[CC_V_BIT] = 1'b0; + end + + ALUOP_SBC: + begin + {cc_out[CC_C_BIT], ALUFn[7:0]} = {1'b0, a_arg} - {1'b0, b_arg} - cc_arg[CC_C_BIT]; + cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]); + end + + default: + ALUFn = 8'H00; + + endcase + + cc_out[CC_N_BIT] = ALUFn[7]; + cc_out[CC_Z_BIT] = (ALUFn == 8'H00); + ALUInst = {cc_out[7:0], ALUFn[7:0]}; +end +endfunction + + +// Top 8 bits == CC, bottom 8 bits = output value +wire [15:0] ALU = ALUInst(ALU_OP, ALU_A, ALU_B, ALU_CC); + +//////////////////////////////////////////////////////////// + +localparam TYPE_INHERENT = 3'd0; +localparam TYPE_IMMEDIATE = 3'd1; +localparam TYPE_DIRECT = 3'd2; +localparam TYPE_RELATIVE = 3'd3; +localparam TYPE_INDEXED = 3'd4; +localparam TYPE_EXTENDED = 3'd5; + +localparam TYPE_INVALID = 3'd7; + +// Function to decode the addressing mode the instruction uses +function [2:0] addressing_mode_type(input [7:0] inst); +begin + casex (inst) + 8'b0000???? : addressing_mode_type = TYPE_DIRECT; + 8'b0001???? : + begin + casex (inst[3:0]) + 4'b0010: + addressing_mode_type = TYPE_INHERENT; + + 4'b0011: + addressing_mode_type = TYPE_INHERENT; + + 4'b1001: + addressing_mode_type = TYPE_INHERENT; + + 4'b1101: + addressing_mode_type = TYPE_INHERENT; + + 4'b0110: + addressing_mode_type = TYPE_RELATIVE; + + 4'b0111: + addressing_mode_type = TYPE_RELATIVE; + + 4'b1010: + addressing_mode_type = TYPE_IMMEDIATE; + + 4'b1100: + addressing_mode_type = TYPE_IMMEDIATE; + + 4'b1110: + addressing_mode_type = TYPE_IMMEDIATE; + + 4'b1111: + addressing_mode_type = TYPE_IMMEDIATE; + + default: + addressing_mode_type = TYPE_INVALID; + endcase + end + + 8'b0010????: addressing_mode_type = TYPE_RELATIVE; + 8'b0011????: + begin + casex(inst[3:0]) + 4'b00??: + addressing_mode_type = TYPE_INDEXED; + + 4'b01??: + addressing_mode_type = TYPE_IMMEDIATE; + + 4'b1001: + addressing_mode_type = TYPE_INHERENT; + + 4'b101?: + addressing_mode_type = TYPE_INHERENT; + + 4'b1100: + addressing_mode_type = TYPE_INHERENT; + + 4'b1101: + addressing_mode_type = TYPE_INHERENT; + + 4'b1111: + addressing_mode_type = TYPE_INHERENT; + + default: + addressing_mode_type = TYPE_INVALID; + endcase + end + + 8'b010?????: addressing_mode_type = TYPE_INHERENT; + + 8'b0110????: addressing_mode_type = TYPE_INDEXED; + + 8'b0111????: addressing_mode_type = TYPE_EXTENDED; + + 8'b1000????: + begin + casex (inst[3:0]) + 4'b0111: addressing_mode_type = TYPE_INVALID; + 4'b1111: addressing_mode_type = TYPE_INVALID; + 4'b1101: addressing_mode_type = TYPE_RELATIVE; + default: addressing_mode_type = TYPE_IMMEDIATE; + endcase + end + + 8'b1001????: addressing_mode_type = TYPE_DIRECT; + 8'b1010????: addressing_mode_type = TYPE_INDEXED; + 8'b1011????: addressing_mode_type = TYPE_EXTENDED; + 8'b1100????: addressing_mode_type = TYPE_IMMEDIATE; + 8'b1101????: addressing_mode_type = TYPE_DIRECT; + 8'b1110????: addressing_mode_type = TYPE_INDEXED; + 8'b1111????: addressing_mode_type = TYPE_EXTENDED; + + endcase +end +endfunction + +wire [2:0] AddrModeType = addressing_mode_type(Inst1); + +////////////////////////////////////////////////// + +// Individual opcodes that are the top of a column of states. + +localparam OPCODE_INH_ABX = 8'H3A; +localparam OPCODE_INH_RTS = 8'H39; +localparam OPCODE_INH_RTI = 8'H3B; +localparam OPCODE_INH_CWAI = 8'H3C; +localparam OPCODE_INH_MUL = 8'H3D; +localparam OPCODE_INH_SWI = 8'H3F; +localparam OPCODE_INH_SEX = 8'H1D; +localparam OPCODE_INH_NOP = 8'H12; +localparam OPCODE_INH_SYNC = 8'H13; +localparam OPCODE_INH_DAA = 8'H19; + +localparam OPCODE_IMM_ORCC = 8'H1A; +localparam OPCODE_IMM_ANDCC = 8'H1C; +localparam OPCODE_IMM_EXG = 8'H1E; +localparam OPCODE_IMM_TFR = 8'H1F; +localparam OPCODE_IMM_PSHS = 8'H34; +localparam OPCODE_IMM_PULS = 8'H35; +localparam OPCODE_IMM_PSHU = 8'H36; +localparam OPCODE_IMM_PULU = 8'H37; + +localparam OPCODE_IMM_SUBD = 8'H83; +localparam OPCODE_IMM_CMPX = 8'H8C; +localparam OPCODE_IMM_LDX = 8'H8E; +localparam OPCODE_IMM_ADDD = 8'HC3; +localparam OPCODE_IMM_LDD = 8'HCC; +localparam OPCODE_IMM_LDU = 8'HCE; +localparam OPCODE_IMM_CMPD = 8'H83; // Page2 +localparam OPCODE_IMM_CMPY = 8'H8C; // Page2 +localparam OPCODE_IMM_LDY = 8'H8E; // Page2 +localparam OPCODE_IMM_LDS = 8'HCE; // Page2 +localparam OPCODE_IMM_CMPU = 8'H83; // Page3 +localparam OPCODE_IMM_CMPS = 8'H8C; // Page3 + +localparam EXGTFR_REG_D = 4'H0; +localparam EXGTFR_REG_X = 4'H1; +localparam EXGTFR_REG_Y = 4'H2; +localparam EXGTFR_REG_U = 4'H3; +localparam EXGTFR_REG_S = 4'H4; +localparam EXGTFR_REG_PC = 4'H5; +localparam EXGTFR_REG_A = 4'H8; +localparam EXGTFR_REG_B = 4'H9; +localparam EXGTFR_REG_CC = 4'HA; +localparam EXGTFR_REG_DP = 4'HB; + +function IsALU8Set0(input [7:0] instr); +reg result; +reg [3:0] hi; +reg [3:0] lo; +begin + hi = instr[7:4]; + lo = instr[3:0]; + if ( (hi == 4'H0) || (hi == 4'H4) || (hi == 4'H5) || (hi == 4'H6) || (hi == 4'H7) ) + begin + if ( (lo != 4'H1) && (lo != 4'H2) && (lo != 4'H5) && (lo != 4'HB) && (lo != 4'HE) ) // permit NEG, COM, LSR, ROR, ASR, ASL/LSL, ROL, DEC, INC, TST, CLR + result = 1; + else + result = 0; + end + else + result = 0; + IsALU8Set0 = result; +end +endfunction + +function IsALU8Set1(input [7:0] instr); +reg result; +reg [3:0] hi; +reg [3:0] lo; +begin + hi = instr[7:4]; + lo = instr[3:0]; + if ( (hi >= 4'H8) ) + begin + if ( (lo <= 4'HB) && (lo != 4'H3) && (lo != 4'H7) ) // 8-bit SUB, CMP, SBC, AND, BIT, LD, EOR, ADC, OR, ADD + result = 1; + else + result = 0; + end + else + result = 0; + IsALU8Set1 = result; +end +endfunction + +// Determine if the instruction is performing an 8-bit op (ALU only) +function ALU8BitOp(input [7:0] instr); +begin + ALU8BitOp = IsALU8Set0(instr) | IsALU8Set1(instr); +end +endfunction + +wire Is8BitInst = ALU8BitOp(Inst1); + +function IsRegA(input [7:0] instr); +reg result; +reg [3:0] hi; +begin + hi = instr[7:4]; + if ((hi == 4'H4) || (hi == 4'H8) || (hi == 4'H9) || (hi == 4'HA) || (hi == 4'HB) ) + result = 1; + else + result = 0; + IsRegA = result; +end +endfunction + +wire IsTargetRegA = IsRegA(Inst1); + +// +// +// Decode +// 00-0F = DIRECT +// 10-1F = INHERENT, RELATIVE, IMMEDIATE +// 20-2F = RELATIVE +// 30-3F = INDEXED, IMMEDIATE (pus, pul), INHERENT +// 40-4F = INHERENT +// 50-5F = INHERENT +// 60-6F = INDEXED +// 70-7F = EXTENDED +// 80-8F = IMMEDIATE, RELATIVE (BSR) +// 90-9F = DIRECT +// A0-AF = INDEXED +// B0-BF = EXTENDED +// C0-CF = IMMEDIATE +// D0-DF = DIRECT +// E0-EF = INDEXED +// F0-FF = EXTENDED + +// DIRECT; 00-0F, 90-9F, D0-DF +// INHERENT; 10-1F (12, 13, 19, 1D), 30-3F (39-3F), 40-4F, 50-5F, +// RELATIVE: 10-1F (16, 17), 20-2F, 80-8F (8D) +// IMMEDIATE: 10-1F (1A, 1C, 1E, 1F), 30-3F (34-37), 80-8F (80-8C, 8E), C0-CF +// INDEXED: 60-6F, A0-AF, E0-EF +// EXTENDED: 70-7F, B0-Bf, F0-FF + +localparam INST_LBRA = 8'H16; // always -- shitty numbering, damnit +localparam INST_LBSR = 8'H17; // + +localparam INST_BRA = 8'H20; // always +localparam INST_BRN = 8'H21; // never +localparam INST_BHI = 8'H22; // CC.Z = 0 && CC.C = 0 +localparam INST_BLS = 8'H23; // CC.Z != 0 && CC.C != 0 +localparam INST_BCC = 8'H24; // CC.C = 0 +localparam INST_BHS = 8'H24; // same as BCC +localparam INST_BCS = 8'H25; // CC.C = 1 +localparam INST_BLO = 8'H25; // same as BCS +localparam INST_BNE = 8'H26; // CC.Z = 0 +localparam INST_BEQ = 8'H27; // CC.Z = 1 +localparam INST_BVC = 8'H28; // V = 1 +localparam INST_BVS = 8'H29; // V = 0 +localparam INST_BPL = 8'H2A; // CC.N = 0 +localparam INST_BMI = 8'H2B; // CC.N = 1 +localparam INST_BGE = 8'H2C; // CC.N = CC.V +localparam INST_BLT = 8'H2D; // CC.N != CC.V +localparam INST_BGT = 8'H2E; // CC.N = CC.V && CC.Z = 0 +localparam INST_BLE = 8'H2F; // CC.N != CC.V && CC.Z = 1 +localparam INST_BSR = 8'H8D; // always + +localparam NYB_BRA = 4'H0; // always +localparam NYB_BRN = 4'H1; // never +localparam NYB_BHI = 4'H2; // CC.Z = 0 && CC.C = 0 +localparam NYB_BLS = 4'H3; // CC.Z != 0 && CC.C != 0 +localparam NYB_BCC = 4'H4; // CC.C = 0 +localparam NYB_BHS = 4'H4; // same as BCC +localparam NYB_BCS = 4'H5; // CC.C = 1 +localparam NYB_BLO = 4'H5; // same as BCS +localparam NYB_BNE = 4'H6; // CC.Z = 0 +localparam NYB_BEQ = 4'H7; // CC.Z = 1 +localparam NYB_BVC = 4'H8; // V = 0 +localparam NYB_BVS = 4'H9; // V = 1 +localparam NYB_BPL = 4'HA; // CC.N = 0 +localparam NYB_BMI = 4'HB; // CC.N = 1 +localparam NYB_BGE = 4'HC; // CC.N = CC.V +localparam NYB_BLT = 4'HD; // CC.N != CC.V +localparam NYB_BGT = 4'HE; // CC.N = CC.V && CC.Z = 0 +localparam NYB_BLE = 4'HF; // CC.N != CC.V && CC.Z = 1 + + + +function take_branch(input [7:0] Inst1, input [7:0] cc); +begin + take_branch = 0; //default + if ( (Inst1 == INST_BSR) || (Inst1 == INST_LBSR) || (Inst1 == INST_LBRA) ) + take_branch = 1; + else + case (Inst1[3:0]) + NYB_BRA: + take_branch = 1; + NYB_BRN: + take_branch = 0; + NYB_BHI: + if ( ( cc[CC_Z_BIT] | cc[CC_C_BIT] ) == 0) + take_branch = 1; + NYB_BLS: + if ( cc[CC_Z_BIT] | cc[CC_C_BIT] ) + take_branch = 1; + NYB_BCC: + if ( cc[CC_C_BIT] == 0 ) + take_branch = 1; + NYB_BCS: + if ( cc[CC_C_BIT] == 1 ) + take_branch = 1; + NYB_BNE: + if ( cc[CC_Z_BIT] == 0 ) + take_branch = 1; + NYB_BEQ: + if ( cc[CC_Z_BIT] == 1 ) + take_branch = 1; + NYB_BVC: + if ( cc[CC_V_BIT] == 0) + take_branch = 1; + NYB_BVS: + if ( cc[CC_V_BIT] == 1) + take_branch = 1; + NYB_BPL: + if ( cc[CC_N_BIT] == 0 ) + take_branch = 1; + NYB_BMI: + if (cc[CC_N_BIT] == 1) + take_branch = 1; + NYB_BGE: + if ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 0) + take_branch = 1; + NYB_BLT: + if ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 1) + take_branch = 1; + NYB_BGT: + if ( ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 0) & (cc[CC_Z_BIT] == 0) ) + take_branch = 1; + NYB_BLE: + if ( ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 1) | (cc[CC_Z_BIT] == 1) ) + take_branch = 1; + endcase +end +endfunction + +wire TakeBranch = take_branch(Inst1, cc); + +///////////////////////////////////////////////////////////////////// +// Convenience function for knowing the contents for TFR, EXG +function [15:0] EXGTFRRegister(input [3:0] regid); +begin + case (regid) + EXGTFR_REG_D: + EXGTFRRegister = {a, b}; + EXGTFR_REG_X: + EXGTFRRegister = x; + EXGTFR_REG_Y: + EXGTFRRegister = y; + EXGTFR_REG_U: + EXGTFRRegister = u; + EXGTFR_REG_S: + EXGTFRRegister = s; + EXGTFR_REG_PC: + EXGTFRRegister = pc_p1; // For both EXG and TFR, this is used on the 2nd byte in the instruction's cycle. The PC intended to transfer is actually the next byte. + EXGTFR_REG_DP: + EXGTFRRegister = {8'HFF, dp}; + EXGTFR_REG_A: + EXGTFRRegister = {8'HFF, a}; + EXGTFR_REG_B: + EXGTFRRegister = {8'HFF, b}; + EXGTFR_REG_CC: + EXGTFRRegister = {8'HFF, cc}; + default: + EXGTFRRegister = 16'H0; + endcase +end +endfunction +wire [15:0] EXGTFRRegA = EXGTFRRegister(D[7:4]); +wire [15:0] EXGTFRRegB = EXGTFRRegister(D[3:0]); + +// CPU state machine +always @(*) +begin + rLIC = 1'b0; + rAVMA = 1'b1; + rBUSY = 1'b0; + + addr_nxt = 16'HFFFF; + pc_p1 = (pc+16'H1); + pc_p2 = (pc+16'H2); + pc_p3 = (pc+16'H3); + s_p1 = (s+16'H1); + s_m1 = (s-16'H1); + u_p1 = (u+16'H1); + u_m1 = (u-16'H1); + addr_p1 = (addr+16'H1); + ea_p1 = (ea+16'H1); + BS_nxt = 1'b0; + BA_nxt = 1'b0; + + // These may be overridden below, but the "next" version by default should be + // the last latched version. + IntType_nxt = IntType; + NMIClear_nxt = NMIClear; + NextState_nxt = NextState; + a_nxt = a; + b_nxt = b; + x_nxt = x; + y_nxt = y; + s_nxt = s; + u_nxt = u; + cc_nxt = cc; + dp_nxt = dp; + pc_nxt = pc; + tmp_nxt = tmp; + ea_nxt = ea; + + ALU_A = 8'H00; + ALU_B = 8'H00; + ALU_CC = 8'H00; + ALU_OP = 5'H00; + + ALU16_OP = 3'H0; + ALU16_A = 16'H0000; + ALU16_B = 16'H0000; + ALU16_CC = 8'H00; + + DOutput = 8'H00; + RnWOut = 1'b1; // read + + Inst1_nxt = Inst1; + Inst2_nxt = Inst2; + Inst3_nxt = Inst3; + InstPage2_nxt = InstPage2; + InstPage3_nxt = InstPage3; + + CpuState_nxt = CpuState; + + case (CpuState) + CPUSTATE_RESET: + begin + addr_nxt = 16'HFFFF; + a_nxt = 0; + b_nxt = 0; + x_nxt = 0; + y_nxt = 0; + s_nxt = 16'HFFFD; // Take care about removing the reset of S. There's logic depending on the delta between s and s_nxt to clear NMIMask. + u_nxt = 0; + cc_nxt = CC_F | CC_I; // reset disables interrupts + dp_nxt = 0; + ea_nxt = 16'HFFFF; + + RnWOut = 1; // read + rLIC = 1'b0; // Instruction incomplete + NMIClear_nxt= 1'b0; + IntType_nxt = 3'b111; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_RESET0; + end + + CPUSTATE_RESET0: + begin + addr_nxt = `RESET_VECTOR; + rBUSY = 1'b1; + pc_nxt[15:8] = D[7:0]; + BS_nxt = 1'b1; // ACK RESET + rAVMA = 1'b1; + rLIC = 1'b1; + CpuState_nxt = CPUSTATE_RESET2; + end + + CPUSTATE_RESET2: + begin + addr_nxt = addr_p1; + BS_nxt = 1'b1; // ACK RESET + pc_nxt[7:0] = D[7:0]; + rAVMA = 1'b1; + rLIC = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_FETCH_I1: + begin + if (~DMABREQLatched) + begin + addr_nxt = pc; + RnWOut = 1'b1; + rAVMA = 1'b0; + tmp_nxt = {tmp[15:4], 4'b1111}; + BS_nxt = 1'b1; + BA_nxt = 1'b1; + rLIC = 1'b1; + CpuState_nxt = CPUSTATE_DMABREQ; + end + else if (~HALTLatched) + begin + addr_nxt = pc; + RnWOut = 1'b1; + rAVMA = 1'b0; + BS_nxt = 1'b1; + BA_nxt = 1'b1; + rLIC = 1'b1; + CpuState_nxt = CPUSTATE_HALTED; + end + else // not halting, run the inst byte fetch + begin + addr_nxt = pc; // Set the address bus for the next instruction, first byte + pc_nxt = pc_p1; + RnWOut = 1; // Set for a READ + Inst1_nxt = MappedInstruction; + InstPage2_nxt = 0; + InstPage3_nxt = 0; + + // New instruction fetch; service interrupts pending + if (NMILatched == 0) + begin + pc_nxt = pc; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_NMI_START; + end + else if ((FIRQLatched == 0) && (cc[CC_F_BIT] == 0)) + begin + pc_nxt = pc; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FIRQ_START; + end + else if ((IRQLatched == 0) && (cc[CC_I_BIT] == 0)) + begin + pc_nxt = pc; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IRQ_START; + end + + // The actual 1st byte checks + else if (Inst1_nxt == 8'H10) // Page 2 Note, like the 6809, $10 $10 $10 $10 has the same effect as a single $10. + begin + InstPage2_nxt = 1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1V2; + end + else if (Inst1_nxt == 8'H11) // Page 3 + begin + InstPage3_nxt = 1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1V2; + end + else + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I2; + end + end // if not halting + end + + CPUSTATE_FETCH_I1V2: + begin + addr_nxt = pc; // Set the address bus for the next instruction, first byte + pc_nxt = pc_p1; + RnWOut = 1; // Set for a READ + Inst1_nxt = MappedInstruction; + + if (Inst1_nxt == 8'H10) // Page 2 Note, like the 6809, $10 $10 $10 $10 has the same effect as a single $10. + begin + if (InstPage3 == 0) // $11 $11 $11 $11 ... $11 $10 still = Page 3 + InstPage2_nxt = 1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1V2; + end + else if (Inst1_nxt == 8'H11) // Page 3 + begin + if (InstPage2 == 0) // $10 $10 ... $10 $11 still = Page 2 + InstPage3_nxt = 1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1V2; + end + else + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I2; + end + end + + + CPUSTATE_FETCH_I2: // We've fetched the first byte. If a $10 or $11 (page select), mark those flags and fetch the next byte as instruction byte 1. + begin + addr_nxt = addr_p1; // Address bus++ + pc_nxt = pc_p1; + Inst2_nxt = D[7:0]; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + + if (IsIllegalInstruction) // Skip illegal instructions + begin + + rAVMA = 1'b1; + CpuState_nxt = IllegalInstructionState; + rLIC = 1'b1; + end + else + begin + // First byte Decode for this stage + case (AddrModeType) + TYPE_INDEXED: + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_INDEXED_BASE; + end + + + TYPE_EXTENDED: + begin + ea_nxt[15:8] = Inst2_nxt; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_EXTENDED_ADDRLO; + end + TYPE_DIRECT: + begin + ea_nxt = {dp, Inst2_nxt}; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_DIRECT_DONTCARE; + end + + TYPE_INHERENT: + begin + if (Inst1 == OPCODE_INH_NOP) + begin + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else if (Inst1 == OPCODE_INH_DAA) // Bcd lunacy + begin + if ( ((cc[CC_C_BIT]) || (a[7:4] > 4'H9)) || + ((a[7:4] > 4'H8) && (a[3:0] > 4'H9)) ) + tmp_nxt[7:4] = 4'H6; + else + tmp_nxt[7:4] = 4'H0; + + if ((cc[CC_H_BIT]) || (a[3:0] > 4'H9)) + tmp_nxt[3:0] = 4'H6; + else + tmp_nxt[3:0] = 4'H0; + + // DAA handles carry in the weirdest way. + // If it's already set, it remains set, even if carry-out is 0. + // If it wasn't set, but the output of the operation is set, carry-out gets set. + {tmp_nxt[8], a_nxt} = {1'b0, a} + tmp_nxt[7:0]; + + cc_nxt[CC_C_BIT] = cc_nxt[CC_C_BIT] | tmp_nxt[8]; + + cc_nxt[CC_N_BIT] = a_nxt[7]; + cc_nxt[CC_Z_BIT] = (a_nxt == 8'H00); + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else if (Inst1 == OPCODE_INH_SYNC) + begin + CpuState_nxt = CPUSTATE_SYNC; + rLIC = 1'b1; + rAVMA = 1'b0; + end + else if (Inst1 == OPCODE_INH_MUL) + begin + tmp_nxt = 16'H0000; + ea_nxt[15:8] = 8'H00; + ea_nxt[7:0] = a; + a_nxt = 8; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_MUL_ACTION; + end + else if (Inst1 == OPCODE_INH_RTS) + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_RTS_HI; + end + else if (Inst1 == OPCODE_INH_RTI) + begin + rAVMA = 1'b1; + tmp_nxt = 16'H1001; // Set tmp[12] to indicate an RTI being processed, and at least pull CC. + CpuState_nxt = CPUSTATE_PUL_ACTION; + NextState_nxt = CPUSTATE_FETCH_I1; + end + else if (Inst1 == OPCODE_INH_SWI) + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_SWI_START; + end + else if (Inst1 == OPCODE_INH_CWAI) + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_CWAI; + end + else if (Inst1 == OPCODE_INH_SEX) + begin + a_nxt = {8{b[7]}}; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else if (Inst1 == OPCODE_INH_ABX) + begin + x_nxt = x + b; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_ABX_DONTCARE; + end + else + begin + ALU_OP = ALU8Op; + if (IsTargetRegA) + ALU_A = a; + else + ALU_A = b; + + ALU_B = 0; + ALU_CC = cc; + cc_nxt = ALU[15:8]; + + if (ALU8Writeback) + begin + if (IsTargetRegA) + a_nxt = ALU[7:0]; + else + b_nxt = ALU[7:0]; + end + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + if (IsOneByteInstruction(Inst1)) // This check is probably superfluous. Every inherent instruction is 1 byte on the 6809. + pc_nxt = pc; // The 6809 auto-reads 2 bytes for every instruction. :( Adjust by not incrementing PC on the 2nd byte read. + end + + TYPE_IMMEDIATE: + begin + if (IsSpecialImmediate) + begin + if (Inst1 == OPCODE_IMM_ANDCC) + begin + pc_nxt = pc_p1; + cc_nxt = cc & D; //cc_nxt & Inst2_nxt; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_CC_DONTCARE; + end + else if (Inst1 == OPCODE_IMM_ORCC) + begin + pc_nxt = pc_p1; + cc_nxt = cc | D; //cc_nxt | Inst2_nxt; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_CC_DONTCARE; + end + else if ( (Inst1 == OPCODE_IMM_PSHS) | (Inst1 == OPCODE_IMM_PSHU) ) + begin + pc_nxt = pc_p1; + tmp_nxt[15] = 1'b0; + tmp_nxt[14] = Inst1[1]; // Mark whether to save to U or S. + tmp_nxt[13] = 1'b0; // Not pushing due to an interrupt. + tmp_nxt[13:8] = 6'H00; + tmp_nxt[7:0] = Inst2_nxt; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_PSH_DONTCARE1; + NextState_nxt = CPUSTATE_FETCH_I1; + end + else if ( (Inst1 == OPCODE_IMM_PULS) | (Inst1 == OPCODE_IMM_PULU) ) + begin + pc_nxt = pc_p1; + tmp_nxt[15] = 1'b0; + tmp_nxt[14] = Inst1[1]; // S (0) or U (1) stack in use. + tmp_nxt[13:8] = 6'H00; + tmp_nxt[7:0] = Inst2_nxt; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_PUL_DONTCARE1; + NextState_nxt = CPUSTATE_FETCH_I1; + end + else if (Inst1 == OPCODE_IMM_TFR) + begin + // The second byte lists the registers; Top nybble is reg #1, bottom is reg #2. + + case (Inst2_nxt[3:0]) + EXGTFR_REG_D: + {a_nxt,b_nxt} = EXGTFRRegA; + EXGTFR_REG_X: + x_nxt = EXGTFRRegA; + EXGTFR_REG_Y: + y_nxt = EXGTFRRegA; + EXGTFR_REG_U: + u_nxt = EXGTFRRegA; + EXGTFR_REG_S: + s_nxt = EXGTFRRegA; + EXGTFR_REG_PC: + pc_nxt = EXGTFRRegA; + EXGTFR_REG_DP: + dp_nxt = EXGTFRRegA[7:0]; + EXGTFR_REG_A: + a_nxt = EXGTFRRegA[7:0]; + EXGTFR_REG_B: + b_nxt = EXGTFRRegA[7:0]; + EXGTFR_REG_CC: + cc_nxt = EXGTFRRegA[7:0]; + default: + begin + end + endcase + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_TFR_DONTCARE1; + + end + else if (Inst1 == OPCODE_IMM_EXG) + begin + // The second byte lists the registers; Top nybble is reg #1, bottom is reg #2. + + case (Inst2_nxt[7:4]) + EXGTFR_REG_D: + {a_nxt,b_nxt} = EXGTFRRegB; + EXGTFR_REG_X: + x_nxt = EXGTFRRegB; + EXGTFR_REG_Y: + y_nxt = EXGTFRRegB; + EXGTFR_REG_U: + u_nxt = EXGTFRRegB; + EXGTFR_REG_S: + s_nxt = EXGTFRRegB; + EXGTFR_REG_PC: + pc_nxt = EXGTFRRegB; + EXGTFR_REG_DP: + dp_nxt = EXGTFRRegB[7:0]; + EXGTFR_REG_A: + a_nxt = EXGTFRRegB[7:0]; + EXGTFR_REG_B: + b_nxt = EXGTFRRegB[7:0]; + EXGTFR_REG_CC: + cc_nxt = EXGTFRRegB[7:0]; + default: + begin + end + endcase + case (Inst2_nxt[3:0]) + EXGTFR_REG_D: + {a_nxt,b_nxt} = EXGTFRRegA; + EXGTFR_REG_X: + x_nxt = EXGTFRRegA; + EXGTFR_REG_Y: + y_nxt = EXGTFRRegA; + EXGTFR_REG_U: + u_nxt = EXGTFRRegA; + EXGTFR_REG_S: + s_nxt = EXGTFRRegA; + EXGTFR_REG_PC: + pc_nxt = EXGTFRRegA; + EXGTFR_REG_DP: + dp_nxt = EXGTFRRegA[7:0]; + EXGTFR_REG_A: + a_nxt = EXGTFRRegA[7:0]; + EXGTFR_REG_B: + b_nxt = EXGTFRRegA[7:0]; + EXGTFR_REG_CC: + cc_nxt = EXGTFRRegA[7:0]; + default: + begin + end + endcase + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_EXG_DONTCARE1; + end + end + // Determine if this is an 8-bit ALU operation. + else if (Is8BitInst) + begin + ALU_OP = ALU8Op; + if (IsTargetRegA) + ALU_A = a; + else + ALU_A = b; + + ALU_B = Inst2_nxt; + ALU_CC = cc; + cc_nxt = ALU[15:8]; + + if (ALU8Writeback) + begin + if (IsTargetRegA) + a_nxt = ALU[7:0]; + else + b_nxt = ALU[7:0]; + end + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else // Then it must be a 16 bit instruction + begin + // 83 SUBD + // 8C CMPX + // 8E LDX + // C3 ADDD + // CC LDD + // CE LDU + // 108E CMPD + // 108C CMPY + // 108E LDY + // 10CE LDS + // 1183 CMPU + // 118C CMPS + // Wow, they were just stuffing them in willy-nilly ... + + // LD* 16 bit immediate + if (IsALU16Opcode) + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_16IMM_LO; + end + // there's a dead zone here; I need an else to take us back to CPUSTATE_FETCHI1 if we want to ignore illegal instructions, to CPUSTATE_DEAD if we want to catch them. + + end + + end + + TYPE_RELATIVE: + begin + // Is this a LB** or a B**? + // If InstPage2 is set, it's a long branch; if clear, a normal branch. + if ( (InstPage2) || (Inst1 == INST_LBRA) || (Inst1 == INST_LBSR) ) + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_LBRA_OFFSETLOW; + end + else + begin + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_BRA_DONTCARE; + end + + end + default: + begin + CpuState_nxt = CPUSTATE_FETCH_I1; + end + endcase + end + end + + + CPUSTATE_LBRA_OFFSETLOW: + begin + addr_nxt = pc; + pc_nxt = pc_p1; + Inst3_nxt = D[7:0]; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_LBRA_DONTCARE; + end + + CPUSTATE_LBRA_DONTCARE: + begin + addr_nxt = 16'HFFFF; + if ( TakeBranch ) + begin + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_LBRA_DONTCARE2; + end + else + begin + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + end + + CPUSTATE_BRA_DONTCARE: + begin + addr_nxt = 16'HFFFF; + tmp_nxt = pc; + if (TakeBranch) + begin + pc_nxt = pc + { {8{Inst2[7]}}, Inst2[7:0]}; // Sign-extend the 8 bit offset to 16. + + if (Inst1 == INST_BSR) + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_BSR_DONTCARE1; + end + else + begin + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + end + else + begin + rLIC = 1'b1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + end + + CPUSTATE_LBRA_DONTCARE2: + begin + tmp_nxt= pc; + addr_nxt = 16'HFFFF; + + // Take branch + pc_nxt = pc + {Inst2[7:0], Inst3[7:0]}; + if (Inst1 == INST_LBSR) + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_BSR_DONTCARE1; + end + else + begin + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + end + + CPUSTATE_BSR_DONTCARE1: + begin + addr_nxt = pc; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_BSR_DONTCARE2; + end + + CPUSTATE_BSR_DONTCARE2: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_BSR_RETURNLOW; + end + + CPUSTATE_BSR_RETURNLOW: + begin + addr_nxt = s_m1; + s_nxt = s_m1; + DOutput[7:0] = tmp[7:0]; + RnWOut = 0; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_BSR_RETURNHIGH; + end + + CPUSTATE_BSR_RETURNHIGH: + begin + addr_nxt = s_m1; + s_nxt = s_m1; + DOutput[7:0] = tmp[15:8]; + RnWOut = 0; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; // after this, RnWOut must go to 1, and the bus needs the PC placed on it. + end + + CPUSTATE_TFR_DONTCARE1: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_TFR_DONTCARE2; + end + + CPUSTATE_TFR_DONTCARE2: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_TFR_DONTCARE3; + end + + CPUSTATE_TFR_DONTCARE3: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_TFR_DONTCARE4; + end + + CPUSTATE_TFR_DONTCARE4: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + rLIC = 1'b1; // Instruction done! + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_EXG_DONTCARE1: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_EXG_DONTCARE2; + end + + CPUSTATE_EXG_DONTCARE2: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_EXG_DONTCARE3; + end + + CPUSTATE_EXG_DONTCARE3: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_EXG_DONTCARE4; + end + + CPUSTATE_EXG_DONTCARE4: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_EXG_DONTCARE5; + end + + CPUSTATE_EXG_DONTCARE5: + begin + rAVMA = 1'b0; + addr_nxt = 16'HFFFF; + CpuState_nxt = CPUSTATE_EXG_DONTCARE6; + end + + CPUSTATE_EXG_DONTCARE6: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + rLIC = 1'b1; // Instruction done! + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_ABX_DONTCARE: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + rLIC = 1'b1; // Instruction done! + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_RTS_HI: + begin + addr_nxt = s; + s_nxt = s_p1; + pc_nxt[15:8] = D[7:0]; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_RTS_LO; + end + + CPUSTATE_RTS_LO: + begin + addr_nxt = s; + s_nxt = s_p1; + pc_nxt[7:0] = D[7:0]; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_RTS_DONTCARE2; + end + + CPUSTATE_RTS_DONTCARE2: + begin + addr_nxt = 16'HFFFF; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_16IMM_LO: + begin + addr_nxt = pc; + pc_nxt = pc_p1; + + ALU16_OP = ALU16Opcode; + ALU16_CC = cc; + ALU16_B = {Inst2, D[7:0]}; + + case (ALU16Reg) + ALU16_REG_X: + ALU16_A = x; + ALU16_REG_D: + ALU16_A = {a, b}; + ALU16_REG_Y: + ALU16_A = y; + ALU16_REG_U: + ALU16_A = u; + ALU16_REG_S: + ALU16_A = s; + default: + ALU16_A = 16'H0; + endcase + + if (ALU16OpWriteback) + begin + case (ALU16Reg) + ALU16_REG_X: + {cc_nxt, x_nxt} = ALU16; + ALU16_REG_D: + {cc_nxt, a_nxt, b_nxt} = ALU16; + ALU16_REG_Y: + {cc_nxt, y_nxt} = ALU16; + ALU16_REG_U: + {cc_nxt, u_nxt} = ALU16; + ALU16_REG_S: + {cc_nxt, s_nxt} = ALU16; + default: + begin + end + endcase + end + else + cc_nxt = ALU16[23:16]; + + if (ALU16_OP == ALUOP16_LD) + begin + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else + begin + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_16IMM_DONTCARE; + end + end + + CPUSTATE_DIRECT_DONTCARE: + begin + addr_nxt = 16'HFFFF; + + if (IsJMP(Inst1)) + begin + pc_nxt = ea; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_ALU_EA; + end + end + + CPUSTATE_ALU_EA: + begin + + // Is Figure 18/5 Column 2? JMP (not Immediate Mode) + // This actually isn't done here. All checks passing in to ALU_EA should check for a JMP; FIXME EVERYWHERE + + // Is Figure 18/5 Column 8? TST (not immediate mode) + // THIS IS BURIED IN THE COLUMN 3 section with comparisons to ALUOP_TST. + + // Is Figure 18/5 Column 3? + if (IsALU8Set1(Inst1)) + begin + addr_nxt = ea; + + ALU_OP = ALU8Op; + ALU_B = D[7:0]; + ALU_CC = cc; + + if (IsTargetRegA) + ALU_A = a; + else + ALU_A = b; + + cc_nxt = ALU[15:8]; + + if ( (ALU8Writeback) ) + begin + if (IsTargetRegA) + a_nxt = ALU[7:0]; + else + b_nxt = ALU[7:0]; + end + + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + // Is Figure 18/5 Column 4? (Store, 8 bits) + else if (IsStore8) + begin + addr_nxt = ea; + RnWOut = 0; // write + + ALU_OP = ALUOP_LD; // load has the same CC characteristics as store + ALU_A = 8'H00; + ALU_CC = cc; + + case (Store8RegisterNum) + ST8_REG_A: + begin + DOutput = a; + ALU_B = a; + end + ST8_REG_B: + begin + DOutput = b; + ALU_B = b; + end + + + endcase + + cc_nxt = ALU[15:8]; + + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + // Is Figure 18/5 Column 5? (Load, 16 bits) + else if (IsALU16Opcode & (ALU16Opcode == ALUOP16_LD)) + begin + addr_nxt = ea; + ea_nxt = ea_p1; + + case (ALU16Reg) + ALU16_REG_X: + x_nxt[15:8] = D[7:0]; + ALU16_REG_D: + a_nxt = D[7:0]; + ALU16_REG_Y: + y_nxt[15:8] = D[7:0]; + ALU16_REG_S: + s_nxt[15:8] = D[7:0]; + ALU16_REG_U: + u_nxt[15:8] = D[7:0]; + default: + begin + end + endcase + rAVMA = 1'b1; + rBUSY = 1'b1; + CpuState_nxt = CPUSTATE_LD16_LO; + + end + + // Is Figure 18/5 Column 6? (Store, 16 bits) + else if (IsStore16) + begin + addr_nxt = ea; + ea_nxt = ea_p1; + + ALU16_OP = ALUOP16_LD; // LD and ST have the same CC characteristics + ALU16_CC = cc; + ALU16_A = 8'H00; + + case (StoreRegisterNum) + ST16_REG_X: + begin + DOutput[7:0] = x[15:8]; + ALU16_B = x; + end + ST16_REG_Y: + begin + DOutput[7:0] = y[15:8]; + ALU16_B = y; + end + ST16_REG_U: + begin + DOutput[7:0] = u[15:8]; + ALU16_B = u; + end + ST16_REG_S: + begin + DOutput[7:0] = s[15:8]; + ALU16_B = s; + end + ST16_REG_D: + begin + DOutput[7:0] = a[7:0]; + ALU16_B = {a,b}; + end + default: + begin + end + endcase + + cc_nxt = ALU16[23:16]; + + RnWOut = 0; // Write + rAVMA = 1'b1; + rBUSY = 1'b1; + CpuState_nxt = CPUSTATE_ST16_LO; + end + + // Is Figure 18/5 Column 7? + else if (IsALU8Set0(Inst1)) + begin + // These are registerless instructions, ala + // ASL, ASR, CLR, COM, DEC, INC, (LSL), LSR, NEG, ROL, ROR + // and TST (special!) + // They require READ, Modify (the operation above), WRITE. Between the Read and the Write cycles, there's actually a /VMA + // cycle where the 6809 likely did the operation. We'll include a /VMA cycle for accuracy, but we'll do the work primarily in the first cycle. + addr_nxt = ea; + + ALU_OP = ALU8Op; + ALU_A = D[7:0]; + ALU_CC = cc; + tmp_nxt[15:8] = cc; // for debug only + tmp_nxt[7:0] = ALU[7:0]; + cc_nxt = ALU[15:8]; + if (ALU8Op == ALUOP_TST) + begin + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_TST_DONTCARE1; + end + else + begin + rAVMA = 1'b0; + rBUSY = 1'b1; + CpuState_nxt = CPUSTATE_ALU_DONTCARE; + end + + end + + // Is Figure 18/5 Column 8? TST + // NOTE: + // THIS IS BURIED IN THE COLUMN 3 section with comparisons to ALUOP_TST. [Directly above.] + + + // Is Figure 18/5 Column 9? (16-bit ALU ops, non-load) + else if (IsALU16Opcode && (ALU16Opcode != ALUOP16_LD) && ((Inst1 < 8'H30) || (Inst1 > 8'H33)) ) // 30-33 = LEAX, LEAY, LEAS, LEAU; don't include them here. + begin + addr_nxt = ea; + ea_nxt = ea_p1; + + tmp_nxt[15:8] = D[7:0]; + rAVMA = 1'b1; + rBUSY = 1'b1; + CpuState_nxt = CPUSTATE_ALU16_LO; + + end + + // Is Figure 18/5 Column 10? JSR (not Immediate Mode) + else if ((Inst1 == 8'H9D) || (Inst1 == 8'HAD) || (Inst1 == 8'HBD)) // JSR + begin + pc_nxt = ea; + addr_nxt = ea; + tmp_nxt = pc; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_JSR_DONTCARE; + end + // Is Figure 18/5 Column 11? LEA(X,Y,S,U) + else if ((Inst1 >= 8'H30) && (Inst1<= 8'H33)) + begin + addr_nxt = 16'HFFFF; // Ack, actually a valid cycle, this isn't a dontcare (/VMA) cycle! + + ALU16_OP = ALU16Opcode; + ALU16_CC = cc; + ALU16_A = ea; + + case (ALU16Reg) + ALU16_REG_X: + {cc_nxt, x_nxt} = ALU16; + ALU16_REG_Y: + {cc_nxt, y_nxt} = ALU16; + ALU16_REG_U: + u_nxt = ALU16[15:0]; + ALU16_REG_S: + s_nxt = ALU16[15:0]; + default: + begin + end + endcase + + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + + end + + end + + + CPUSTATE_ALU_DONTCARE: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + rBUSY = 1'b1; // We do nothing here, but on the real 6809, they did the modify phase here. :| + CpuState_nxt = CPUSTATE_ALU_WRITEBACK; + end + + CPUSTATE_ALU_WRITEBACK: + begin + addr_nxt = ea; + RnWOut = 0; // Write + DOutput = tmp[7:0]; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_LD16_LO: + begin + addr_nxt = ea; + + case (ALU16Reg) + ALU16_REG_X: + begin + x_nxt[7:0] = D[7:0]; + ALU16_B[15:8] = x[15:8]; + end + ALU16_REG_D: + begin + b_nxt = D[7:0]; + ALU16_B[15:8] = a; + end + ALU16_REG_Y: + begin + y_nxt[7:0] = D[7:0]; + ALU16_B[15:8] = y[15:8]; + end + ALU16_REG_S: + begin + s_nxt[7:0] = D[7:0]; + ALU16_B[15:8] = s[15:8]; + end + ALU16_REG_U: + begin + u_nxt[7:0] = D[7:0]; + ALU16_B[15:8] = u[15:8]; + end + default: + begin + end + + endcase + + ALU16_OP = ALU16Opcode; + ALU16_CC = cc; + ALU16_A = 8'H00; + ALU16_B[7:0] = D[7:0]; + cc_nxt = ALU16[23:16]; + + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_ST16_LO: + begin + addr_nxt = ea; + ea_nxt = ea_p1; + case (StoreRegisterNum) + ST16_REG_X: + DOutput[7:0] = x[7:0]; + ST16_REG_Y: + DOutput[7:0] = y[7:0]; + ST16_REG_U: + DOutput[7:0] = u[7:0]; + ST16_REG_S: + DOutput[7:0] = s[7:0]; + ST16_REG_D: + DOutput[7:0] = b[7:0]; + default: + begin + end + endcase + RnWOut = 0; // write + + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_ALU16_LO: + begin + addr_nxt = ea; + + ALU16_OP = ALU16Opcode; + ALU16_CC = cc; + + ALU16_B = {tmp[15:8], D[7:0]}; + + case (ALU16Reg) + ALU16_REG_X: + ALU16_A = x; + ALU16_REG_D: + ALU16_A = {a, b}; + ALU16_REG_Y: + ALU16_A = y; + ALU16_REG_S: + ALU16_A = s; + ALU16_REG_U: + ALU16_A = u; + default: + ALU16_A = 16'H0; + + endcase + + if (ALU16OpWriteback) + begin + case (ALU16Reg) + ALU16_REG_X: + {cc_nxt, x_nxt} = ALU16; + ALU16_REG_D: + {cc_nxt, a_nxt, b_nxt} = ALU16; + ALU16_REG_Y: + {cc_nxt, y_nxt} = ALU16; + ALU16_REG_U: + {cc_nxt, u_nxt} = ALU16; + ALU16_REG_S: + {cc_nxt, s_nxt} = ALU16; + default: + begin + end + endcase + end + else + cc_nxt = ALU16[23:16]; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_ALU16_DONTCARE; + end + + CPUSTATE_ALU16_DONTCARE: + begin + addr_nxt = 16'HFFFF; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + + CPUSTATE_JSR_DONTCARE: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_JSR_RETLO; + end + + CPUSTATE_JSR_RETLO: + begin + addr_nxt = s_m1; + s_nxt = s_m1; + RnWOut = 0; + DOutput = tmp[7:0]; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_JSR_RETHI; + end + + CPUSTATE_JSR_RETHI: + begin + addr_nxt = s_m1; + s_nxt = s_m1; + RnWOut = 0; + DOutput = tmp[15:8]; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_EXTENDED_ADDRLO: + begin + addr_nxt = pc; + pc_nxt = pc_p1; + ea_nxt[7:0] = D[7:0]; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_EXTENDED_DONTCARE; + end + + CPUSTATE_EXTENDED_DONTCARE: + begin + addr_nxt = 16'HFFFF; + if (IsJMP(Inst1)) + begin + pc_nxt = ea; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_ALU_EA; + end + end + + CPUSTATE_INDEXED_BASE: + begin + addr_nxt = pc; + + Inst3_nxt = D[7:0]; + + case (IndexedRegister) + IDX_REG_X: + ALU16_A = x; + IDX_REG_Y: + ALU16_A = y; + IDX_REG_U: + ALU16_A = u; + IDX_REG_S: + ALU16_A = s; + IDX_REG_PC: + ALU16_A = pc_p1; + default: + ALU16_A = 16'H0; + endcase + ALU16_OP = ALUOP16_ADD; + + case (IndexedMode) + IDX_MODE_NOOFFSET: + begin + case (IndexedRegister) + IDX_REG_X: + ea_nxt = x; + IDX_REG_Y: + ea_nxt = y; + IDX_REG_U: + ea_nxt = u; + IDX_REG_S: + ea_nxt = s; + default: + ea_nxt = 16'H0; + endcase + + if (IndexedIndirect) + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_INDIRECT_HI; + end + else + begin + if (IsJMP(Inst1)) + begin + pc_nxt = ea_nxt; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_ALU_EA; + end + end + end + + IDX_MODE_5BIT_OFFSET: + begin + // The offset is the bottom 5 bits of the Index Postbyte, which is Inst2 here. + // We'll sign-extend it to 16 bits. + ALU16_B = { {11{Inst2[4]}}, Inst2[4:0] }; + ea_nxt = ALU16[15:0]; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_DONTCARE3; + end + + + IDX_MODE_8BIT_OFFSET_PC: + begin + ALU16_B = { {8{D[7]}}, D[7:0] }; + pc_nxt = pc_p1; + ea_nxt = ALU16[15:0]; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_DONTCARE3; + end + + IDX_MODE_8BIT_OFFSET: + begin + ALU16_B = { {8{D[7]}}, D[7:0] }; + pc_nxt = pc_p1; + ea_nxt = ALU16[15:0]; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_DONTCARE3; + end + + IDX_MODE_A_OFFSET: + begin + ALU16_B = { {8{a[7]}}, a[7:0] }; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_DONTCARE3; + ea_nxt = ALU16[15:0]; + end + + IDX_MODE_B_OFFSET: + begin + ALU16_B = { {8{b[7]}}, b[7:0] }; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_DONTCARE3; + ea_nxt = ALU16[15:0]; + end + + IDX_MODE_D_OFFSET: + begin + ALU16_B = {a, b}; + + ea_nxt = ALU16[15:0]; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE1; + end + + IDX_MODE_POSTINC1: + begin + ALU16_B = 16'H1; + ea_nxt = ALU16_A; + case (IndexedRegister) + IDX_REG_X: + x_nxt = ALU16[15:0]; + IDX_REG_Y: + y_nxt = ALU16[15:0]; + IDX_REG_U: + u_nxt = ALU16[15:0]; + IDX_REG_S: + s_nxt = ALU16[15:0]; + default: + begin + end + endcase + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2; + end + + IDX_MODE_POSTINC2: + begin + ALU16_B = 16'H2; + ea_nxt = ALU16_A; + case (IndexedRegister) + IDX_REG_X: + x_nxt = ALU16[15:0]; + IDX_REG_Y: + y_nxt = ALU16[15:0]; + IDX_REG_U: + u_nxt = ALU16[15:0]; + IDX_REG_S: + s_nxt = ALU16[15:0]; + default: + begin + end + endcase + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE0; + end + + IDX_MODE_PREDEC1: + begin + ALU16_B = 16'HFFFF; // -1 + case (IndexedRegister) + IDX_REG_X: + x_nxt = ALU16[15:0]; + IDX_REG_Y: + y_nxt = ALU16[15:0]; + IDX_REG_U: + u_nxt = ALU16[15:0]; + IDX_REG_S: + s_nxt = ALU16[15:0]; + default: + begin + end + endcase + ea_nxt = ALU16[15:0]; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2; + end + + IDX_MODE_PREDEC2: + begin + ALU16_B = 16'HFFFE; // -2 + case (IndexedRegister) + IDX_REG_X: + x_nxt = ALU16[15:0]; + IDX_REG_Y: + y_nxt = ALU16[15:0]; + IDX_REG_U: + u_nxt = ALU16[15:0]; + IDX_REG_S: + s_nxt = ALU16[15:0]; + default: + begin + end + endcase + ea_nxt = ALU16[15:0]; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE0; + end + + IDX_MODE_16BIT_OFFSET_PC: + begin + tmp_nxt[15:8] = D[7:0]; + pc_nxt = pc_p1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IDX_16OFFSET_LO; + end + + IDX_MODE_16BIT_OFFSET: + begin + tmp_nxt[15:8] = D[7:0]; + pc_nxt = pc_p1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IDX_16OFFSET_LO; + end + + IDX_MODE_EXTENDED_INDIRECT: + begin + ea_nxt[15:8] = D[7:0]; + pc_nxt = pc_p1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IDX_EXTIND_LO; + end + + default: + begin + rLIC = 1'b1; + CpuState_nxt = PostIllegalState; + end + + endcase + end + + CPUSTATE_IDX_OFFSET_LO: + begin + tmp_nxt[7:0] = D[7:0]; + addr_nxt = pc; + pc_nxt = pc_p1; + ALU16_B = tmp_nxt; + + case (IndexedRegister) + IDX_REG_X: + ALU16_A = x; + IDX_REG_Y: + ALU16_A = y; + IDX_REG_U: + ALU16_A = u; + IDX_REG_S: + ALU16_A = s; + IDX_REG_PC: + ALU16_A = pc; + default: + ALU16_A = 16'H0; + endcase + ALU16_OP = ALUOP16_ADD; + + ea_nxt = ALU16[15:0]; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE1; + end + + + CPUSTATE_IDX_DONTCARE3: + begin + addr_nxt = 16'HFFFF; + if (IndexedIndirect) + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_INDIRECT_HI; + end + else + begin + if (IsJMP(Inst1)) + begin + pc_nxt = ea; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_ALU_EA; + end + end + + end + + CPUSTATE_IDX_16OFFSET_LO: + begin + addr_nxt = pc; + pc_nxt = pc_p1; + + case (IndexedRegister) + IDX_REG_X: + ALU16_A = x; + IDX_REG_Y: + ALU16_A = y; + IDX_REG_U: + ALU16_A = u; + IDX_REG_S: + ALU16_A = s; + IDX_REG_PC: + ALU16_A = pc_nxt; // Whups; tricky; not part of the actual pattern + default: + ALU16_A = x; // Default to something + endcase + + ALU16_OP = ALUOP16_ADD; + + ALU16_B = {tmp[15:8], D[7:0]}; + + ea_nxt = ALU16[15:0]; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE1; + end + + CPUSTATE_IDX_16OFF_DONTCARE1: + begin + addr_nxt = pc; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2; + end + + CPUSTATE_IDX_16OFF_DONTCARE0: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2; + end + + CPUSTATE_IDX_16OFF_DONTCARE2: + begin + addr_nxt = 16'HFFFF; + if (IndexedRegister == IDX_REG_PC) + begin + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_PC16OFF_DONTCARE; + end + else + begin + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE3; + end + end + + CPUSTATE_IDX_PC16OFF_DONTCARE: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE3; + end + + + CPUSTATE_IDX_16OFF_DONTCARE3: + begin + addr_nxt = 16'HFFFF; + if (IndexedIndirect) + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_INDIRECT_HI; + end + else + begin + if (IsJMP(Inst1)) + begin + pc_nxt = ea; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_ALU_EA; + end + end + end + + CPUSTATE_IDX_DOFF_DONTCARE1: + begin + addr_nxt = pc_p1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE2; + end + + CPUSTATE_IDX_DOFF_DONTCARE2: + begin + addr_nxt = pc_p2; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2; + end + + CPUSTATE_IDX_DOFF_DONTCARE3: + begin + addr_nxt = pc_p3; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE2; + end + + CPUSTATE_IDX_EXTIND_LO: + begin + ea_nxt[7:0] = D[7:0]; + addr_nxt = pc; + pc_nxt = pc_p1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IDX_EXTIND_DONTCARE; + end + + CPUSTATE_IDX_EXTIND_DONTCARE: + begin + addr_nxt = pc; + if (IndexedIndirect) + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_INDIRECT_HI; + end + else + begin + if (IsJMP(Inst1)) + begin + pc_nxt = ea; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_ALU_EA; + end + end + end + + CPUSTATE_INDIRECT_HI: + begin + addr_nxt = ea; + tmp_nxt[15:8] = D[7:0]; + rAVMA = 1'b1; + rBUSY = 1'b1; + CpuState_nxt = CPUSTATE_INDIRECT_LO; + end + + CPUSTATE_INDIRECT_LO: + begin + addr_nxt = ea_p1; + ea_nxt[15:8] = tmp_nxt[15:8]; + ea_nxt[7:0] = D[7:0]; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_INDIRECT_DONTCARE; + end + + CPUSTATE_INDIRECT_DONTCARE: + begin + addr_nxt = 16'HFFFF; + if (IsJMP(Inst1)) + begin + pc_nxt = ea; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + else + begin + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_ALU_EA; + end + end + + CPUSTATE_MUL_ACTION: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + // tmp = result + // ea = additor (the shifted multiplicand) + // a = counter + // b is the multiplier (which gets shifted right) + if (a != 8'H00) + begin + if (b[0]) + begin + tmp_nxt = tmp + ea; + end + ea_nxt = {ea[14:0], 1'b0}; + b_nxt = {1'b0, b[7:1]}; + a_nxt = a - 8'H1; + end + else + begin + {a_nxt, b_nxt} = tmp; + + cc_nxt[CC_Z_BIT] = (tmp == 0); + cc_nxt[CC_C_BIT] = tmp[7]; + rLIC = 1'b1; // Instruction done! + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + end + + CPUSTATE_PSH_DONTCARE1: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_PSH_DONTCARE2; + end + + CPUSTATE_PSH_DONTCARE2: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_PSH_DONTCARE3; + end + + CPUSTATE_PSH_DONTCARE3: + begin + addr_nxt = (Inst1[1]) ? u : s; + + CpuState_nxt = CPUSTATE_PSH_ACTION; + end + + CPUSTATE_PSH_ACTION: + begin + rAVMA = 1'b1; + if (tmp[7] & ~(tmp[15])) // PC_LO + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = pc[7:0]; + RnWOut = 1'b0; // write + tmp_nxt[15] = 1'b1; + end + else if (tmp[7] & (tmp[15])) // PC_HI + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = pc[15:8]; + RnWOut = 1'b0; // write + tmp_nxt[7] = 1'b0; + tmp_nxt[15] = 1'b0; + end + else if (tmp[6] & ~(tmp[15])) // U/S_LO + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = (tmp[14]) ? s[7:0] : u[7:0]; + RnWOut = 1'b0; // write + tmp_nxt[15] = 1'b1; + end + else if (tmp[6] & (tmp[15])) // U/S_HI + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = (tmp[14]) ? s[15:8] : u[15:8]; + RnWOut = 1'b0; // write + tmp_nxt[6] = 1'b0; + tmp_nxt[15] = 1'b0; + end + else if (tmp[5] & ~(tmp[15])) // Y_LO + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = y[7:0]; + RnWOut = 1'b0; // write + tmp_nxt[15] = 1'b1; + end + else if (tmp[5] & (tmp[15])) // Y_HI + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = y[15:8]; + RnWOut = 1'b0; // write + tmp_nxt[5] = 1'b0; + tmp_nxt[15] = 1'b0; + end + else if (tmp[4] & ~(tmp[15])) // X_LO + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = x[7:0]; + RnWOut = 1'b0; // write + tmp_nxt[15] = 1'b1; + end + else if (tmp[4] & (tmp[15])) // X_HI + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = x[15:8]; + RnWOut = 1'b0; // write + tmp_nxt[4] = 1'b0; + tmp_nxt[15] = 1'b0; + end + else if (tmp[3]) // DP + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = dp; + RnWOut = 1'b0; // write + tmp_nxt[3] = 1'b0; + end + else if (tmp[2]) // B + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = b; + RnWOut = 1'b0; // write + tmp_nxt[2] = 1'b0; + end + else if (tmp[1]) // A + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = a; + RnWOut = 1'b0; // write + tmp_nxt[1] = 1'b0; + end + else if (tmp[0]) // CC + begin + addr_nxt = (tmp[14]) ? u_m1 : s_m1; + if (tmp[14]) + u_nxt = u_m1; + else + s_nxt = s_m1; + DOutput = cc; + RnWOut = 1'b0; // write + tmp_nxt[0] = 1'b0; + end + if (tmp[13]) // Then we're pushing for an IRQ, and LIC is supposed to be set. + rLIC = 1'b1; + if (tmp_nxt[7:0] == 8'H00) + begin + if (NextState == CPUSTATE_FETCH_I1) + begin + rAVMA = 1'b1; + rLIC = 1'b1; + end + else + rAVMA = 1'b0; + CpuState_nxt = NextState; + end + end + + CPUSTATE_PUL_DONTCARE1: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_PUL_DONTCARE2; + end + + CPUSTATE_PUL_DONTCARE2: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_PUL_ACTION; + end + + CPUSTATE_PUL_ACTION: + begin + rAVMA = 1'b1; + if (tmp[0]) // CC + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + cc_nxt = D[7:0]; + if (tmp[12] == 1'b1) // This pull is from an RTI, the E flag comes from the retrieved CC, and set the tmp_nxt accordingly, indicating what other registers to retrieve + begin + if (D[CC_E_BIT]) + tmp_nxt[7:0] = 8'HFE; // Retrieve all registers (ENTIRE) [CC is already retrieved] + else + tmp_nxt[7:0] = 8'H80; // Retrieve PC and CC [CC is already retrieved] + end + else + tmp_nxt[0] = 1'b0; + end + else if (tmp[1]) // A + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + a_nxt = D[7:0]; + tmp_nxt[1] = 1'b0; + end + else if (tmp[2]) // B + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + b_nxt = D[7:0]; + tmp_nxt[2] = 1'b0; + end + else if (tmp[3]) // DP + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + dp_nxt = D[7:0]; + tmp_nxt[3] = 1'b0; + end + else if (tmp[4] & (~tmp[15])) // X_HI + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + x_nxt[15:8] = D[7:0]; + tmp_nxt[15] = 1'b1; + end + else if (tmp[4] & tmp[15]) // X_LO + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + x_nxt[7:0] = D[7:0]; + tmp_nxt[4] = 1'b0; + tmp_nxt[15] = 1'b0; + end + else if (tmp[5] & (~tmp[15])) // Y_HI + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + y_nxt[15:8] = D[7:0]; + tmp_nxt[15] = 1'b1; + end + else if (tmp[5] & tmp[15]) // Y_LO + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + y_nxt[7:0] = D[7:0]; + tmp_nxt[5] = 1'b0; + tmp_nxt[15] = 1'b0; + end + else if (tmp[6] & (~tmp[15])) // U/S_HI + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + if (tmp[14]) + s_nxt[15:8] = D[7:0]; + else + u_nxt[15:8] = D[7:0]; + tmp_nxt[15] = 1'b1; + end + else if (tmp[6] & tmp[15]) // U/S_LO + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + if (tmp[14]) + s_nxt[7:0] = D[7:0]; + else + u_nxt[7:0] = D[7:0]; + tmp_nxt[6] = 1'b0; + tmp_nxt[15] = 1'b0; + end + else if (tmp[7] & (~tmp[15])) // PC_HI + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + pc_nxt[15:8] = D[7:0]; + tmp_nxt[15] = 1'b1; + end + else if (tmp[7] & tmp[15]) // PC_LO + begin + addr_nxt = (tmp[14]) ? u : s; + if (tmp[14]) + u_nxt = u_p1; + else + s_nxt = s_p1; + pc_nxt[7:0] = D[7:0]; + tmp_nxt[7] = 1'b0; + tmp_nxt[15] = 1'b0; + end + else + begin + addr_nxt = (tmp[14]) ? u : s; + if (NextState == CPUSTATE_FETCH_I1) + begin + rAVMA = 1'b1; + rLIC = 1'b1; + end + else + rAVMA = 1'b0; + CpuState_nxt = NextState; + end + end + + CPUSTATE_NMI_START: + begin + NMIClear_nxt = 1'b1; + addr_nxt = pc; + // tmp stands as the bits to push to the stack + tmp_nxt = 16'H20FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC; set LIC on every push + NextState_nxt = CPUSTATE_IRQ_DONTCARE2; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_IRQ_DONTCARE; + IntType_nxt = INTTYPE_NMI; + cc_nxt[CC_E_BIT] = 1'b1; + end + + CPUSTATE_IRQ_START: + begin + addr_nxt = pc; + tmp_nxt = 16'H20FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC; set LIC on every push + NextState_nxt = CPUSTATE_IRQ_DONTCARE2; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IRQ_DONTCARE; + IntType_nxt = INTTYPE_IRQ; + cc_nxt[CC_E_BIT] = 1'b1; + end + + CPUSTATE_FIRQ_START: + begin + addr_nxt = pc; + tmp_nxt = 16'H2081; // Save to the S stack, PC, CC; set LIC on every push + NextState_nxt = CPUSTATE_IRQ_DONTCARE2; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IRQ_DONTCARE; + IntType_nxt = INTTYPE_FIRQ; + cc_nxt[CC_E_BIT] = 1'b0; + end + + CPUSTATE_SWI_START: + begin + addr_nxt = pc; + tmp_nxt = 16'H00FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC + + NextState_nxt = CPUSTATE_IRQ_DONTCARE2; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IRQ_DONTCARE; + if (InstPage3) + IntType_nxt = INTTYPE_SWI3; + if (InstPage2) + IntType_nxt = INTTYPE_SWI2; + else + IntType_nxt = INTTYPE_SWI; + + cc_nxt[CC_E_BIT] = 1'b1; + end + + CPUSTATE_IRQ_DONTCARE: + begin + NMIClear_nxt = 1'b0; + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_PSH_ACTION; + end + + + CPUSTATE_IRQ_DONTCARE2: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI; + rLIC = 1'b1; + end + + CPUSTATE_IRQ_VECTOR_HI: + begin + case (IntType) + INTTYPE_NMI: + begin + addr_nxt = `NMI_VECTOR; + BS_nxt = 1'b1; // ACK Interrupt + end + INTTYPE_IRQ: + begin + addr_nxt = `IRQ_VECTOR; + BS_nxt = 1'b1; // ACK Interrupt + end + INTTYPE_SWI: + begin + addr_nxt = `SWI_VECTOR; + end + INTTYPE_FIRQ: + begin + addr_nxt = `FIRQ_VECTOR; + BS_nxt = 1'b1; // ACK Interrupt + end + INTTYPE_SWI2: + begin + addr_nxt = `SWI2_VECTOR; + end + INTTYPE_SWI3: + begin + addr_nxt = `SWI3_VECTOR; + end + default: // make the default an IRQ, even though it really should never happen + begin + addr_nxt = `IRQ_VECTOR; + BS_nxt = 1'b1; // ACK Interrupt + end + endcase + + pc_nxt[15:8] = D[7:0]; + rAVMA = 1'b1; + rBUSY = 1'b1; + rLIC = 1'b1; + CpuState_nxt = CPUSTATE_IRQ_VECTOR_LO; + + + end + + CPUSTATE_IRQ_VECTOR_LO: + begin + case (IntType) + INTTYPE_NMI: + begin + addr_nxt = `NMI_VECTOR+16'H1; + cc_nxt[CC_I_BIT] = 1'b1; + cc_nxt[CC_F_BIT] = 1'b1; + BS_nxt = 1'b1; // ACK Interrupt + end + INTTYPE_IRQ: + begin + addr_nxt = `IRQ_VECTOR+16'H1; + cc_nxt[CC_I_BIT] = 1'b1; + BS_nxt = 1'b1; // ACK Interrupt + end + INTTYPE_SWI: + begin + addr_nxt = `SWI_VECTOR+16'H1; + cc_nxt[CC_F_BIT] = 1'b1; + cc_nxt[CC_I_BIT] = 1'b1; + rLIC = 1'b1; + end + INTTYPE_FIRQ: + begin + addr_nxt = `FIRQ_VECTOR+16'H1; + cc_nxt[CC_F_BIT] = 1'b1; + cc_nxt[CC_I_BIT] = 1'b1; + BS_nxt = 1'b1; // ACK Interrupt + end + INTTYPE_SWI2: + begin + addr_nxt = `SWI2_VECTOR+16'H1; + rLIC = 1'b1; + end + INTTYPE_SWI3: + begin + addr_nxt = `SWI3_VECTOR+16'H1; + rLIC = 1'b1; + end + default: + begin + end + endcase + + pc_nxt[7:0] = D[7:0]; + rAVMA = 1'b1; + rLIC = 1'b1; + CpuState_nxt = CPUSTATE_INT_DONTCARE; + end + + CPUSTATE_INT_DONTCARE: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + rLIC = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_CC_DONTCARE: + begin + addr_nxt = pc; + rLIC = 1'b1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_TST_DONTCARE1: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_TST_DONTCARE2; + end + + CPUSTATE_TST_DONTCARE2: + begin + addr_nxt = 16'HFFFF; + rLIC = 1'b1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_DEBUG: + begin + addr_nxt = tmp; + rLIC = 1'b1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_16IMM_DONTCARE: + begin + addr_nxt = 16'HFFFF; + rLIC = 1'b1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_SYNC: + begin + addr_nxt = 16'HFFFF; + BA_nxt = 1'b1; + rLIC = 1'b1; + rAVMA = 1'b0; + + if (~(NMILatched & FIRQLatched & IRQLatched)) + begin + CpuState_nxt = CPUSTATE_SYNC_EXIT; + end + end + + CPUSTATE_SYNC_EXIT: + begin + addr_nxt = 16'HFFFF; + BA_nxt = 1'b1; + rLIC = 1'b1; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + + CPUSTATE_DMABREQ: + begin + rAVMA = 1'b0; + addr_nxt = 16'HFFFF; + BS_nxt = 1'b1; + BA_nxt = 1'b1; + rLIC = 1'b1; + tmp_nxt[3:0] = tmp[3:0] - 1'b1; + if ( (tmp[3:0] == 4'H0) | (DMABREQSample2) ) + begin + CpuState_nxt = CPUSTATE_DMABREQ_EXIT; + end + end + + CPUSTATE_DMABREQ_EXIT: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_HALTED: + begin + rAVMA = 1'b0; + addr_nxt = 16'HFFFF; + BS_nxt = 1'b1; + BA_nxt = 1'b1; + rLIC = 1'b1; + if (HALTSample2) + begin + CpuState_nxt = CPUSTATE_HALT_EXIT2; + end + end + + + CPUSTATE_HALT_EXIT2: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_FETCH_I1; + end + + CPUSTATE_STOP: + begin + addr_nxt = 16'HDEAD; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_STOP2; + end + + CPUSTATE_STOP2: + begin + addr_nxt = pc; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_STOP3; + end + + CPUSTATE_STOP3: + begin + addr_nxt = 16'H0000; //{Inst1, Inst2}; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_STOP; + end + + // The otherwise critically useful Figure 18 in the 6809 datasheet contains an error; + // it lists that CWAI has a tri-stated bus while it waits for an interrupt. + // That is not true. SYNC tristates the bus, as do things like /HALT and /DMABREQ. + // CWAI does not. It waits with /VMA cycles on the bus until an interrupt occurs. + // The implementation here fits with the 6809 Programming Manual and other Motorola + // sources, not with that typo in Figure 18. + CPUSTATE_CWAI: + begin + addr_nxt = pc; + cc_nxt = {1'b1, (cc[6:0] & Inst2[6:0])}; // Set E flag, AND CC with CWAI argument + tmp_nxt = 16'H00FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC + + NextState_nxt = CPUSTATE_CWAI_POST; + rAVMA = 1'b0; + CpuState_nxt = CPUSTATE_CWAI_DONTCARE1; + end + + CPUSTATE_CWAI_DONTCARE1: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b1; + CpuState_nxt = CPUSTATE_PSH_ACTION; + end + + CPUSTATE_CWAI_POST: + begin + addr_nxt = 16'HFFFF; + rAVMA = 1'b0; + + CpuState_nxt = CPUSTATE_CWAI_POST; + + // Wait for an interrupt + if (NMILatched == 0) + begin + rAVMA = 1'b1; + IntType_nxt = INTTYPE_NMI; + cc_nxt[CC_F_BIT] = 1'b1; + cc_nxt[CC_I_BIT] = 1'b1; + CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI; + end + else if ((FIRQLatched == 0) && (cc[CC_F_BIT] == 0)) + begin + rAVMA = 1'b1; + cc_nxt[CC_F_BIT] = 1'b1; + cc_nxt[CC_I_BIT] = 1'b1; + IntType_nxt = INTTYPE_FIRQ; + CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI; + end + else if ((IRQLatched == 0) && (cc[CC_I_BIT] == 0)) + begin + rAVMA = 1'b1; + cc_nxt[CC_I_BIT] = 1'b1; + IntType_nxt = INTTYPE_IRQ; + CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI; + end + end + + default: // Picky darned Verilog. + begin + CpuState_nxt = PostIllegalState; + end + + endcase +end + +endmodule + From dd21affa1bf2d0d847cc73b8244e2fc4ab451785 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Sat, 18 Jan 2020 21:36:27 +0100 Subject: [PATCH 2/2] Robotron-FPGA: Works, Sinistar has minor issues and no speech Should work with Robotron 2048, Joust, Sinistar, Splat, Bubbles, Stargate --- .../Robotron-FPGA/README.md | 192 + .../Robotron-FPGA/RobotronFPGA.qpf | 31 + .../Robotron-FPGA/RobotronFPGA.qsf | 231 + .../Robotron-FPGA/RobotronFPGA.sdc | 138 + .../Robotron-FPGA/buildall.sh | 16 + .../Robotron-FPGA/clean.bat | 15 + .../Robotron-FPGA/rtl/RobotronFPGA_MiST.sv | 354 ++ .../Robotron-FPGA/rtl/build_id.tcl | 35 + .../Robotron-FPGA/rtl/cpu68.vhd | 3963 +++++++++++++++++ .../rtl/defender_sound_board.vhd | 184 + .../Robotron-FPGA/rtl/dpram.vhd | 81 + .../Robotron-FPGA/rtl/gen_ram.vhd | 84 + .../Robotron-FPGA/rtl/pll_mist.qip | 4 + .../Robotron-FPGA/rtl/pll_mist.vhd | 429 ++ .../rtl/robotron_cpu/decoder_4.vhd | 54 + .../rtl/robotron_cpu/decoder_6.vhd | 54 + .../rtl/robotron_cpu/robotron_cpu.vhd | 1096 +++++ .../rtl/robotron_cpu/robotron_cpu_test.vhd | 363 ++ .../Robotron-FPGA/rtl/robotron_cpu/sc1.vhd | 240 + .../Robotron-FPGA/rtl/robotron_cpu/sc1_tb.vhd | 160 + .../Robotron-FPGA/rtl/robotron_soc.vhd | 262 ++ .../Robotron-FPGA/rtl/sdram.sv | 253 ++ 22 files changed, 8239 insertions(+) create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/README.md create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qpf create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qsf create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.sdc create mode 100755 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/buildall.sh create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/clean.bat create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/RobotronFPGA_MiST.sv create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/build_id.tcl create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/cpu68.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/defender_sound_board.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/dpram.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/gen_ram.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.qip create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_4.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_6.vhd create mode 100755 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu.vhd create mode 100755 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu_test.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1.vhd create mode 100755 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1_tb.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_soc.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/sdram.sv diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/README.md b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/README.md new file mode 100644 index 00000000..f0291cc6 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/README.md @@ -0,0 +1,192 @@ +robotron-fpga MiST port +======================= + +Supported games: Robotron 2048, Joust, Sinistar, Bubbles, Splat, Stargate + +After loading the RBF, a CMOS clearing will happen. Reset the core to start +the game. + +Sinistar has some graphics issues, and the speech chip is not implemented. + +robotron-fpga +============= + +An implementation of the classic Robotron: 2084 video arcade game from 1982. +Both the sound board and CPU/interface boards are implemented, but are in +separate sub-projects at the moment. The CPU/interface implementation relies +on a Motorola MC6809E processor attached to the FPGA board via an adapter +board design that is part of this project. + +![robotron-cpu on NEXYS2 FPGA board](https://github.com/sharebrained/robotron-fpga/raw/master/doc/photo/robotron-on-nexys2.jpg) + +The goal is to have a complete Robotron: 2084 game implemented in a single, +compact, inexpensive FPGA board which includes the necessary peripherals: +video and sound outputs, joysticks interface, and coin/player buttons. + +Status +====== + +The CPU/interface and sound boards are implemented as separate projects. +Both appear to function well. + +The MC6809E breakout board has been fabricated, but has some design issues +that need to be addressed. The primary issue is the lack of pull-up/-down +resistors on key MC6809E signals, to keep the processor in a RESET state +until the FPGA board is ready to work with the MC6809E. I also screwed up +and put the NEXYS2 connector on the "bottom side" of the board. Smooth! + +Documentation +============= + +These documents served me well during development of this project. + +[Sean Riddle](http://seanriddle.com/) - Williams arcade machine information, +including Robotron: 2084. + +* [Hardware overview](http://seanriddle.com/willhard.html) +* [Memory map](http://seanriddle.com/memmap.gif) +* [Processor and video timing](http://seanriddle.com/timing.html) +* [BLTter description and test code](http://seanriddle.com/blittest.html) + +[Robotron-2084](http://www.robotron-2084.co.uk/) - Williams arcade machine +official documentation. + +* [Robotron schematics and instruction manuals](http://www.robotron-2084.co.uk/manualsrobotron.html) +* [Defender "later series" theory of operation](http://www.robotron-2084.co.uk/manualsdefender.html), + interesting because the Robotron and Defender hardware is quite + similar. + +Documentation for various ICs in the original Robotron: 2084 machine. + +* [MC6809E microprocessor datasheet](http://www.classiccmp.org/dunfield/r/6809e.pdf) +* [MC6809E microprocessor programming manual](http://www.classiccmp.org/dunfield/r/6809prog.pdf) +* [DM9316 Synchronous 4-Bit Binary Counter](http://www.ti.com/product/dm9316) +* National Semiconductor(?) DM7489 64-bit random access read/write memory + (no good reference) +* [Harris HM-7641 512 x 8 PROM](http://www.bitsavers.org/pdf/harris/_dataBooks/1978_Harris_Memory_Vol1.pdf) (page 2-35) +* [Harris HM-6514 1024 x 4 CMOS RAM](http://www.bitsavers.org/pdf/harris/_dataBooks/1978_Harris_Memory_Vol1.pdf) (page 3-49) +* [Mostek MK4116 16,384 x 1 bit dynamic RAM](http://hardware.speccy.org/datasheet/MK4116.pdf) +* [Signetics 8T97 hex buffer](http://www.bitsavers.org/pdf/signetics/_dataBooks/1977_Bipolar_Microprocessor.pdf) (page 96) +* [Various 74-series logic ICs](http://www.ti.com/lsds/ti/logic/home_overview.page) + +[Digilent](http://www.digilentinc.com/) - FPGA development boards and +accessories. + +* [NEXYS2 FPGA development board](http://digilentinc.com/Products/Detail.cfm?NavPath=2,400,789&Prod=NEXYS2) + +[Xilinx](http://www.xilinx.com/) - FPGA silicon and tools vendor. + +* [Spartan-3E documentation](http://www.xilinx.com/support/documentation/spartan-3e.htm) + +Requirements +============ + +* Digilent NEXYS2 Spartan-3E FPGA development board. + + This is the board I've done my development on, and is a good choice + because it has plenty of inputs, a VGA output connector, many switches + and LEDs, and enough onboard RAM and flash to meet the game's memory + needs. + +* Williams Robotron: 2084 ROM binary files: + + These files are often used with MAME, the arcade emulator. CPU board + ROM files are named "robotron.sb?", where "?" is "1" through "9" and + "a" through "c". The sound board ROM file is named "robotron.snd". + +* Python 2.7: + + Used to transform ROM and PROM files into VHDL files. + +* Xilinx ISE WebPack 13.4: + + For compiling VHDL and generating the bit file for the FPGA. + +* Digilent Adept or other JTAG tool: + + For loading the bit file into FPGA board. + +* VGA monitor: + + Video output is 31.25 kHz horizontal sync and 60 Hz vertical sync, + which is compatible with VGA monitors. The output is line-doubled + from the arcade game's original 15.625 kHz horizontal sync. + +* RC lowpass filter: + + The PWM audio output from the FPGA needs filtering to sound reasonable, + or an eight-bit DAC can be attached to the 8-bit audio output pins of + the FPGA board. + +Tools +===== + +* make_rom_file.py: + + Translates a set of Robotron ROM board ROM files + (like those you would use with the MAME arcade emulator) into a + binary file that can be loaded into the flash device on the Digilent + FPGA board. + +* make_decoder_vhdl.py: + + Translates a decoder.4 or decoder.6 file (data + dumped from decoder PROMs on the Robotron CPU board) into a VHDL + file used by the robotron_cpu project. + +* dac_out_wave.py: + + Translates the text file output of robotron_test.vhd + into a WAV file that can be played. + +* make_sound_rom.py: + + Produces rom_snd_blocks.vhd, containing VHDL ROM + blocks, from the contents of a robotron.snd ROM file. The + robotron.snd file is not provided due to copyright on the original + ROM binaries produced by Williams. I happen to have a physical + instance of the ROM board, so I'm in the clear. :-) + +Contributing +============ + +Contributions are welcome! + +Please respect Williams Electronics' copyright and do not post any VHDL +or .bit files containing their binary code. + +License +======= + +This hardware design is licensed under a +[Creative Commons Attribution-ShareAlike 3.0 Unported License] +(http://creativecommons.org/licenses/by-sa/3.0/). + +The associated software is provided under the GNU Public License, +version 3: + +This project is free software: you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This project is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this project. If not, see . + +Contact +======= + +Jared Boone + +ShareBrained Technology, Inc. + + + + +The latest version of this repository can be found at +https://github.com/sharebrained/robotron-fpga diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qpf b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qpf new file mode 100644 index 00000000..df002df5 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2017 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 17.0.1 Build 598 06/07/2017 SJ Standard Edition +# Date created = 04:04:47 October 16, 2017 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "17.0" +DATE = "04:04:47 October 16, 2017" + +# Revisions + +PROJECT_REVISION = "RobotronFPGA" diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qsf b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qsf new file mode 100644 index 00000000..bd44a02d --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qsf @@ -0,0 +1,231 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 16:34:25 January 07, 2020 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# RobotronFPGA_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + + +# Project-Wide Assignments +# ======================== +set_global_assignment -name PROJECT_CREATION_TIME_DATE "21:22:13 JUNE 04, 2019" +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl" +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1 +set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26" +set_global_assignment -name SMART_RECOMPILE ON + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_144 -to VGA_R[5] +set_location_assignment PIN_143 -to VGA_R[4] +set_location_assignment PIN_142 -to VGA_R[3] +set_location_assignment PIN_141 -to VGA_R[2] +set_location_assignment PIN_137 -to VGA_R[1] +set_location_assignment PIN_135 -to VGA_R[0] +set_location_assignment PIN_133 -to VGA_B[5] +set_location_assignment PIN_132 -to VGA_B[4] +set_location_assignment PIN_125 -to VGA_B[3] +set_location_assignment PIN_121 -to VGA_B[2] +set_location_assignment PIN_120 -to VGA_B[1] +set_location_assignment PIN_115 -to VGA_B[0] +set_location_assignment PIN_114 -to VGA_G[5] +set_location_assignment PIN_113 -to VGA_G[4] +set_location_assignment PIN_112 -to VGA_G[3] +set_location_assignment PIN_111 -to VGA_G[2] +set_location_assignment PIN_110 -to VGA_G[1] +set_location_assignment PIN_106 -to VGA_G[0] +set_location_assignment PIN_136 -to VGA_VS +set_location_assignment PIN_119 -to VGA_HS +set_location_assignment PIN_65 -to AUDIO_L +set_location_assignment PIN_80 -to AUDIO_R +set_location_assignment PIN_105 -to SPI_DO +set_location_assignment PIN_88 -to SPI_DI +set_location_assignment PIN_126 -to SPI_SCK +set_location_assignment PIN_127 -to SPI_SS2 +set_location_assignment PIN_91 -to SPI_SS3 +set_location_assignment PIN_13 -to CONF_DATA0 +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +set_location_assignment PIN_59 -to SDRAM_nCS +set_location_assignment PIN_33 -to SDRAM_CKE +set_location_assignment PIN_43 -to SDRAM_CLK + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON +set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL ON + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name TOP_LEVEL_ENTITY RobotronFPGA_MiST + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_NCE_PIN OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + +# Assembler Assignments +# ===================== +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name GENERATE_RBF_FILE ON + +# SignalTap II Assignments +# ======================== +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_global_assignment -name USE_SIGNALTAP_FILE output_files/cpu1.stp + +# Power Estimation Assignments +# ============================ +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" + +# Advanced I/O Timing Assignments +# =============================== +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + +# --------------------------- +# start ENTITY(Defender_MiST) + + # Pin & Location Assignments + # ========================== + + # Fitter Assignments + # ================== + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(Defender_MiST) +# ------------------------- +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_* +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_* +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO +set_global_assignment -name SYSTEMVERILOG_FILE rtl/RobotronFPGA_MiST.sv +set_global_assignment -name VHDL_FILE rtl/defender_sound_board.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv +set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd +set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd +set_global_assignment -name VHDL_FILE rtl/dpram.vhd +set_global_assignment -name VHDL_FILE rtl/cpu68.vhd +set_global_assignment -name VHDL_FILE rtl/robotron_soc.vhd +set_global_assignment -name VHDL_FILE rtl/robotron_cpu/sc1.vhd +set_global_assignment -name VHDL_FILE rtl/robotron_cpu/robotron_cpu.vhd +set_global_assignment -name VHDL_FILE rtl/robotron_cpu/decoder_6.vhd +set_global_assignment -name VHDL_FILE rtl/robotron_cpu/decoder_4.vhd +set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip +set_global_assignment -name VHDL_FILE ../../../common/CPU/MC6809/cpu09l_128a.vhd +set_global_assignment -name VHDL_FILE ../../../common/IO/pia6821.vhd +set_global_assignment -name VERILOG_FILE ../../../common/CPU/MC6809/mc6809i.v +set_global_assignment -name SIGNALTAP_FILE output_files/cpu1.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.sdc b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.sdc new file mode 100644 index 00000000..cad1ec42 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.sdc @@ -0,0 +1,138 @@ +## Generated SDC file "vectrex_MiST.out.sdc" + +## Copyright (C) 1991-2013 Altera Corporation +## Your use of Altera Corporation's design tools, logic functions +## and other software and tools, and its AMPP partner logic +## functions, and any output files from any of the foregoing +## (including device programming or simulation files), and any +## associated documentation or information are expressly subject +## to the terms and conditions of the Altera Program License +## Subscription Agreement, Altera MegaCore Function License +## Agreement, or other applicable license agreement, including, +## without limitation, that your use is for the sole purpose of +## programming logic devices manufactured by Altera and sold by +## Altera or its authorized distributors. Please refer to the +## applicable agreement for further details. + + +## VENDOR "Altera" +## PROGRAM "Quartus II" +## VERSION "Version 13.1.0 Build 162 10/23/2013 SJ Web Edition" + +## DATE "Sun Jun 24 12:53:00 2018" + +## +## DEVICE "EP3C25E144C8" +## + +# Clock constraints + +# Automatically constrain PLL and other generated clocks +derive_pll_clocks -create_base_clocks + +# Automatically calculate clock uncertainty to jitter and other effects. +derive_clock_uncertainty + +# tsu/th constraints + +# tco constraints + +# tpd constraints + +#************************************************************** +# Time Information +#************************************************************** + +set_time_format -unit ns -decimal_places 3 + + + +#************************************************************** +# Create Clock +#************************************************************** + +create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}] + +set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]" +set vid_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +set game_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +set aud_clk "pll|altpll_component|auto_generated|pll1|clk[2]" + +#************************************************************** +# Create Generated Clock +#************************************************************** + + +#************************************************************** +# Set Clock Latency +#************************************************************** + + + +#************************************************************** +# Set Clock Uncertainty +#************************************************************** + +#************************************************************** +# Set Input Delay +#************************************************************** + +set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}] + +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.4 [get_ports SDRAM_DQ[*]] +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.2 [get_ports SDRAM_DQ[*]] + +#************************************************************** +# Set Output Delay +#************************************************************** + +set_output_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}] +set_output_delay -add_delay -clock_fall -clock [get_clocks $aud_clk] 1.000 [get_ports {AUDIO_L}] +set_output_delay -add_delay -clock_fall -clock [get_clocks $aud_clk] 1.000 [get_ports {AUDIO_R}] +set_output_delay -add_delay -clock_fall -clock [get_clocks $sdram_clk] 1.000 [get_ports {LED}] +set_output_delay -add_delay -clock_fall -clock [get_clocks $vid_clk] 1.000 [get_ports {VGA_*}] + +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] + +#************************************************************** +# Set Clock Groups +#************************************************************** + +set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}] +set_clock_groups -asynchronous -group [get_clocks $game_clk] -group [get_clocks $aud_clk] + +#************************************************************** +# Set False Path +#************************************************************** + + + +#************************************************************** +# Set Multicycle Path +#************************************************************** + +set_multicycle_path -to {VGA_*[*]} -setup 2 +set_multicycle_path -to {VGA_*[*]} -hold 1 + +#************************************************************** +# Set Maximum Delay +#************************************************************** + + + +#************************************************************** +# Set Minimum Delay +#************************************************************** + + + +#************************************************************** +# Set Input Transition +#************************************************************** + diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/buildall.sh b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/buildall.sh new file mode 100755 index 00000000..2fa8e228 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/buildall.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +PROJECTS=" \ +ROBOTRON \ +JOUST \ +SPLAT \ +BUBBLES \ +STARGATE \ +SINISTAR" + +mkdir -p Releases +for PROJECT in $PROJECTS; do + echo "Compiling $PROJECT" + sed -i "s/^.define CORE_NAME.*/\`define CORE_NAME \"$PROJECT\"/" rtl/RobotronFPGA_MiST.sv + quartus_sh --flow compile RobotronFPGA.qsf && cp output_files/RobotronFPGA.rbf Releases/$PROJECT.rbf +done \ No newline at end of file diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/clean.bat b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/clean.bat new file mode 100644 index 00000000..c9a2cb06 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/clean.bat @@ -0,0 +1,15 @@ +@echo off +del /s *.bak +del /s *.orig +del /s *.rej +rmdir /s /q db +rmdir /s /q incremental_db +rmdir /s /q output +rmdir /s /q simulation +rmdir /s /q greybox_tmp +del PLLJ_PLLSPE_INFO.txt +del *.qws +del *.ppf +del *.qip +del *.ddb +pause diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/RobotronFPGA_MiST.sv b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/RobotronFPGA_MiST.sv new file mode 100644 index 00000000..c51b7f46 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/RobotronFPGA_MiST.sv @@ -0,0 +1,354 @@ +//============================================================================ +// Robotron-FPGA MiST top-level +// +// Robotron-FPGA is Copyright 2012 ShareBrained Technology, Inc. +// +// Supports: +// Robotron 2048/Joust/Stargate/Bubbles/Splat/Sinistar + +module RobotronFPGA_MiST( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27, + + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nCS, + output [1:0] SDRAM_BA, + output SDRAM_CLK, + output SDRAM_CKE +); + +`include "rtl/build_id.v" + +`define CORE_NAME "ROBOTRON" +//`define CORE_NAME "JOUST" +//`define CORE_NAME "SPLAT" +//`define CORE_NAME "BUBBLES" +//`define CORE_NAME "STARGATE" +//`define CORE_NAME "SINISTAR" + +localparam CONF_STR = { + `CORE_NAME,";ROM;", + "O2,Rotate Controls,Off,On;", + "O34,Scanlines,Off,25%,50%,75%;", + "O5,Blend,Off,On;", + "O6,Swap Joysticks,Off,On;", + "T0,Reset;", + "V,v1.0.",`BUILD_DATE +}; + +wire rotate = status[2]; +wire [1:0] scanlines = status[4:3]; +wire blend = status[5]; +wire joyswap = status[6]; + +reg [7:0] SW; +reg [7:0] JA; +reg [7:0] JB; +reg [3:0] BTN; +reg blitter_sc2, sinistar; +reg [1:0] orientation; // [left/right, landscape/portrait] + +always @(*) begin + orientation = 2'b10; + SW = 8'h00; + blitter_sc2 = 0; + sinistar = 0; + + if (`CORE_NAME == "ROBOTRON") begin + BTN = { m_one_player, m_two_players, m_coin1 | m_coin2, reset }; + JA = ~{ m_right2, m_left2, m_down2, m_up2, m_right, m_left, m_down, m_up }; + JB = ~{ m_right2, m_left2, m_down2, m_up2, m_right, m_left, m_down, m_up }; + end else if (`CORE_NAME == "JOUST") begin + BTN = { m_two_players, m_one_player, m_coin1 | m_coin2, reset }; + JA = ~{ 5'b00000, m_fireA, m_right, m_left }; + JB = ~{ 5'b00000, m_fire2A, m_right2, m_left2 }; + end else if (`CORE_NAME == "SPLAT") begin + blitter_sc2 = 1; + BTN = { m_one_player, m_two_players, m_coin1 | m_coin2, reset }; + JA = ~{ m_right2, m_left2, m_down2, m_up2, m_right, m_left, m_down, m_up }; + JB = ~{ m_right4, m_left4, m_down4, m_up4, m_right3, m_left3, m_down3, m_up3 }; + end else if (`CORE_NAME == "BUBBLES") begin + BTN = { m_two_players, m_one_player, m_coin1 | m_coin2, reset }; + JA = ~{ 4'b0000, m_right, m_left, m_down, m_up }; + JB = ~{ 4'b0000, m_right2, m_left2, m_down2, m_up2 }; + end else if (`CORE_NAME == "STARGATE") begin + BTN = { m_two_players, m_one_player, m_coin1 | m_coin2, reset }; + JA = ~{ m_fireE, m_up, m_down, m_left | m_right, m_fireD, m_fireC, m_fireB, m_fireA }; + JB = ~{ m_fire2E, m_up2, m_down2, m_left2 | m_right2, m_fire2D, m_fire2C, m_fire2B, m_fire2A }; + end else if (`CORE_NAME == "SINISTAR") begin + sinistar = 1; + orientation = 2'b01; + BTN = { m_two_players, m_one_player, m_coin1 | m_coin2, reset }; + JA = { sin_x, 2'b00, m_right | m_left | m_right2 | m_left2, sin_y, 2'b00, m_up | m_down | m_up2 | m_down2 }; + JB = { sin_x, 2'b00, m_right | m_left | m_right2 | m_left2, sin_y, 2'b00, m_up | m_down | m_up2 | m_down2 }; + end +end + +assign LED = ~ioctl_downl; +assign SDRAM_CLK = clk_mem; +assign SDRAM_CKE = 1; + +wire clk_sys, clk_mem, clk_aud; +wire pll_locked; +pll_mist pll( + .inclk0(CLOCK_27), + .areset(0), + .c0(clk_mem),//96 + .c1(clk_sys),//12 + .c2(clk_aud),//0.89 + .locked(pll_locked) + ); + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoublerD; +wire ypbpr; +wire [7:0] audio; +wire hs, vs; +wire blankn; +wire [2:0] r,g; +wire [1:0] b; +wire key_pressed; +wire [7:0] key_code; +wire key_strobe; + +wire ioctl_downl; +wire [7:0] ioctl_index; +wire ioctl_wr; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; + +/* +ROM Structure: +0000-BFFF main cpu 48k +C000-CFFF snd cpu 4k +*/ +data_io data_io ( + .clk_sys ( clk_mem ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS2 ( SPI_SS2 ), + .SPI_DI ( SPI_DI ), + .ioctl_download( ioctl_downl ), + .ioctl_index ( ioctl_index ), + .ioctl_wr ( ioctl_wr ), + .ioctl_addr ( ioctl_addr ), + .ioctl_dout ( ioctl_dout ) +); + +reg port1_req, port2_req; +wire [23:1] mem_addr; +wire [15:0] mem_do; +wire [15:0] mem_di; +wire mem_oe; +wire mem_we; +wire ramcs; +wire romcs; +wire ramlb; +wire ramub; + +reg clkref; +always @(posedge clk_sys) clkref <= ~clkref; + +sdram #(.MHZ(96)) sdram( + .*, + .init_n ( pll_locked ), + .clk ( clk_mem ), + .clkref ( clkref ), + + // ROM upload + .port1_req ( port1_req ), + .port1_ack ( ), + .port1_a ( ioctl_addr[22:0] ), + .port1_ds ( 2'b11 ), + .port1_we ( ioctl_downl ), + .port1_d ( {ioctl_dout[7:4], ioctl_dout[7:4], ioctl_dout[3:0], ioctl_dout[3:0]} ), + .port1_q ( ), + + // CPU/video access + .cpu1_addr ( ioctl_downl ? 17'h1ffff : sdram_addr ), + .cpu1_d ( mem_di ), + .cpu1_q ( mem_do ), + .cpu1_oe ( ~mem_oe & ~(ramcs & romcs) ), + .cpu1_we ( ~mem_we & ~(ramcs & romcs) ), + .cpu1_ds ( ~romcs ? 2'b11 : ~{ramub, ramlb} ) +); + +// ROM address to SDRAM address: +// 0xxx-8xxx -> 0xxx-8xxx +// DXXX-FXXX -> 9xxx-Bxxx +wire [17:1] sdram_addr = ~romcs ? {1'b0, mem_addr[16], ~mem_addr[16] & mem_addr[15], mem_addr[14:1]} : { 1'b1, mem_addr[16:1] }; + +always @(posedge clk_mem) begin + reg ioctl_wr_last = 0; + + ioctl_wr_last <= ioctl_wr; + if (ioctl_downl) begin + if (~ioctl_wr_last && ioctl_wr) begin + port1_req <= ~port1_req; + port2_req <= ~port2_req; + end + end +end + +reg reset = 1; +reg rom_loaded = 0; +always @(posedge clk_sys) begin + reg ioctl_downlD; + ioctl_downlD <= ioctl_downl; + + if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1; + reset <= status[0] | buttons[1] | ioctl_downl | ~rom_loaded; +end + +robotron_soc robotron_soc ( + .clock ( clk_sys ), + .clock_snd ( clk_aud ), + .vgaRed ( r ), + .vgaGreen ( g ), + .vgaBlue ( b ), + .Hsync ( hs ), + .Vsync ( vs ), + .audio_out ( audio ), + + .blitter_sc2 ( blitter_sc2 ), + .sinistar ( sinistar ), + .BTN ( BTN ), + .SIN_FIRE ( ~m_fireA & ~m_fire2A ), + .SIN_BOMB ( ~m_fireB & ~m_fire2B ), + .SW ( SW ), + .JA ( JA ), + .JB ( JB ), + + .MemAdr ( mem_addr ), + .MemDin ( mem_di ), + .MemDout ( mem_do ), + .MemOE ( mem_oe ), + .MemWR ( mem_we ), + .RamCS ( ramcs ), + .RamLB ( ramlb ), + .RamUB ( ramub ), + .FlashCS ( romcs ), + + .dl_clock ( clk_mem ), + .dl_addr ( ioctl_addr[15:0] ), + .dl_data ( ioctl_dout ), + .dl_wr ( ioctl_wr ) +); + +mist_video #(.COLOR_DEPTH(3), .SD_HCNT_WIDTH(11)) mist_video( + .clk_sys ( clk_sys ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS3 ( SPI_SS3 ), + .SPI_DI ( SPI_DI ), + .R ( r ), + .G ( g ), + .B ( {b, b[1] } ), + .HSync ( hs ), + .VSync ( vs ), + .VGA_R ( VGA_R ), + .VGA_G ( VGA_G ), + .VGA_B ( VGA_B ), + .VGA_VS ( VGA_VS ), + .VGA_HS ( VGA_HS ), + .rotate ( {orientation[1],rotate} ), + .scandoubler_disable( scandoublerD ), + .ce_divider ( 1'b1 ), + .scanlines ( scanlines ), + .blend ( blend ), + .ypbpr ( ypbpr ) + ); + +user_io #( + .STRLEN(($size(CONF_STR)>>3))) +user_io( + .clk_sys ( clk_sys ), + .conf_str ( CONF_STR ), + .SPI_CLK ( SPI_SCK ), + .SPI_SS_IO ( CONF_DATA0 ), + .SPI_MISO ( SPI_DO ) , + .SPI_MOSI ( SPI_DI ), + .buttons ( buttons ), + .switches ( switches ), + .scandoubler_disable (scandoublerD ), + .ypbpr ( ypbpr ), + .key_strobe ( key_strobe ), + .key_pressed ( key_pressed ), + .key_code ( key_code ), + .joystick_0 ( joystick_0 ), + .joystick_1 ( joystick_1 ), + .status ( status ) + ); + +wire dac_o; +assign AUDIO_L = dac_o; +assign AUDIO_R = dac_o; + +dac #( + .C_bits(8)) +dac( + .clk_i(clk_aud), + .res_n_i(1), + .dac_i(audio), + .dac_o(dac_o) + ); + +// Sinistar controls +reg sin_x; +reg sin_y; + +always @(posedge clk_sys) begin + if (m_right | m_right2) sin_x <= 0; + else if (m_left | m_left2) sin_x <= 1; + + if (m_up | m_up2) sin_y <= 0; + else if (m_down | m_down2) sin_y <= 1; +end + +// General controls +wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF; +wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F; +wire m_up3, m_down3, m_left3, m_right3, m_fire3A, m_fire3B, m_fire3C, m_fire3D, m_fire3E, m_fire3F; +wire m_up4, m_down4, m_left4, m_right4, m_fire4A, m_fire4B, m_fire4C, m_fire4D, m_fire4E, m_fire4F; +wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players; + +arcade_inputs inputs ( + .clk ( clk_sys ), + .key_strobe ( key_strobe ), + .key_pressed ( key_pressed ), + .key_code ( key_code ), + .joystick_0 ( joystick_0 ), + .joystick_1 ( joystick_1 ), + .rotate ( rotate ), + .orientation ( orientation ), + .joyswap ( joyswap ), + .oneplayer ( 1'b0 ), + .controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ), + .player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ), + .player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} ), + .player3 ( {m_fire3F, m_fire3E, m_fire3D, m_fire3C, m_fire3B, m_fire3A, m_up3, m_down3, m_left3, m_right3} ), + .player4 ( {m_fire4F, m_fire4E, m_fire4D, m_fire4C, m_fire4B, m_fire4A, m_up4, m_down4, m_left4, m_right4} ) +); + +endmodule diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/build_id.tcl b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/cpu68.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/cpu68.vhd new file mode 100644 index 00000000..016bd9a9 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/cpu68.vhd @@ -0,0 +1,3963 @@ +--===========================================================================-- +-- +-- S Y N T H E Z I A B L E CPU68 C O R E +-- +-- www.OpenCores.Org - December 2002 +-- This core adheres to the GNU public license +-- +-- File name : cpu68.vhd +-- +-- Purpose : Implements a 6800 compatible CPU core with some +-- additional instructions found in the 6801 +-- +-- Dependencies : ieee.Std_Logic_1164 +-- ieee.std_logic_unsigned +-- +-- Author : John E. Kent +-- +--===========================================================================---- +-- +-- Revision History: +-- +-- Date: Revision Author +-- 22 Sep 2002 0.1 John Kent +-- +-- 30 Oct 2002 0.2 John Kent +-- made NMI edge triggered +-- +-- 30 Oct 2002 0.3 John Kent +-- more corrections to NMI +-- added wai_wait_state to prevent stack overflow on wai. +-- +-- 1 Nov 2002 0.4 John Kent +-- removed WAI states and integrated WAI with the interrupt service routine +-- replace Data out (do) and Data in (di) register with a single Memory Data (md) reg. +-- Added Multiply instruction states. +-- run ALU and CC out of CPU module for timing measurements. +-- +-- 3 Nov 2002 0.5 John Kent +-- Memory Data Register was not loaded on Store instructions +-- SEV and CLV were not defined in the ALU +-- Overflow Flag on NEG was incorrect +-- +-- 16th Feb 2003 0.6 John Kent +-- Rearranged the execution cycle for dual operand instructions +-- so that occurs during the following fetch cycle. +-- This allows the reduction of one clock cycle from dual operand +-- instruction. Note that this also necessitated re-arranging the +-- program counter so that it is no longer incremented in the ALU. +-- The effective address has also been re-arranged to include a +-- separate added. The STD (store accd) now sets the condition codes. +-- +-- 28th Jun 2003 0.7 John Kent +-- Added Hold and Halt signals. Hold is used to steal cycles from the +-- CPU or add wait states. Halt puts the CPU in the inactive state +-- and is only honoured in the fetch cycle. Both signals are active high. +-- +-- 9th Jan 2004 0.8 John Kent +-- Clear instruction did an alu_ld8 rather than an alu_clr, so +-- the carry bit was not cleared correctly. +-- This error was picked up by Michael Hassenfratz. +-- + +library ieee; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +entity cpu68 is + port ( + clk: in std_logic; + rst: in std_logic; + rw: out std_logic; + vma: out std_logic; + address: out std_logic_vector(15 downto 0); + data_in: in std_logic_vector(7 downto 0); + data_out: out std_logic_vector(7 downto 0); + hold: in std_logic; + halt: in std_logic; + irq: in std_logic; + nmi: in std_logic; + test_alu: out std_logic_vector(15 downto 0); + test_cc: out std_logic_vector(7 downto 0) + ); +end; + +architecture CPU_ARCH of cpu68 is + + constant SBIT : integer := 7; + constant XBIT : integer := 6; + constant HBIT : integer := 5; + constant IBIT : integer := 4; + constant NBIT : integer := 3; + constant ZBIT : integer := 2; + constant VBIT : integer := 1; + constant CBIT : integer := 0; + + type state_type is (reset_state, fetch_state, decode_state, + extended_state, indexed_state, read8_state, read16_state, immediate16_state, + write8_state, write16_state, + execute_state, halt_state, error_state, + mul_state, mulea_state, muld_state, + mul0_state, mul1_state, mul2_state, mul3_state, + mul4_state, mul5_state, mul6_state, mul7_state, + jmp_state, jsr_state, jsr1_state, + branch_state, bsr_state, bsr1_state, + rts_hi_state, rts_lo_state, + int_pcl_state, int_pch_state, + int_ixl_state, int_ixh_state, + int_cc_state, int_acca_state, int_accb_state, + int_wai_state, int_mask_state, + rti_state, rti_cc_state, rti_acca_state, rti_accb_state, + rti_ixl_state, rti_ixh_state, + rti_pcl_state, rti_pch_state, + pula_state, psha_state, pulb_state, pshb_state, + pulx_lo_state, pulx_hi_state, pshx_lo_state, pshx_hi_state, + vect_lo_state, vect_hi_state ); + type addr_type is (idle_ad, fetch_ad, read_ad, write_ad, push_ad, pull_ad, int_hi_ad, int_lo_ad ); + type dout_type is (md_lo_dout, md_hi_dout, acca_dout, accb_dout, ix_lo_dout, ix_hi_dout, cc_dout, pc_lo_dout, pc_hi_dout ); + type op_type is (reset_op, fetch_op, latch_op ); + type acca_type is (reset_acca, load_acca, load_hi_acca, pull_acca, latch_acca ); + type accb_type is (reset_accb, load_accb, pull_accb, latch_accb ); + type cc_type is (reset_cc, load_cc, pull_cc, latch_cc ); + type ix_type is (reset_ix, load_ix, pull_lo_ix, pull_hi_ix, latch_ix ); + type sp_type is (reset_sp, latch_sp, load_sp ); + type pc_type is (reset_pc, latch_pc, load_ea_pc, add_ea_pc, pull_lo_pc, pull_hi_pc, inc_pc ); + type md_type is (reset_md, latch_md, load_md, fetch_first_md, fetch_next_md, shiftl_md ); + type ea_type is (reset_ea, latch_ea, add_ix_ea, load_accb_ea, inc_ea, fetch_first_ea, fetch_next_ea ); + type iv_type is (reset_iv, latch_iv, swi_iv, nmi_iv, irq_iv ); + type nmi_type is (reset_nmi, set_nmi, latch_nmi ); + type left_type is (acca_left, accb_left, accd_left, md_left, ix_left, sp_left ); + type right_type is (md_right, zero_right, plus_one_right, accb_right ); + type alu_type is (alu_add8, alu_sub8, alu_add16, alu_sub16, alu_adc, alu_sbc, + alu_and, alu_ora, alu_eor, + alu_tst, alu_inc, alu_dec, alu_clr, alu_neg, alu_com, + alu_inx, alu_dex, alu_cpx, + alu_lsr16, alu_lsl16, + alu_ror8, alu_rol8, + alu_asr8, alu_asl8, alu_lsr8, + alu_sei, alu_cli, alu_sec, alu_clc, alu_sev, alu_clv, alu_tpa, alu_tap, + alu_ld8, alu_st8, alu_ld16, alu_st16, alu_nop, alu_daa ); + + signal op_code: std_logic_vector(7 downto 0); + signal acca: std_logic_vector(7 downto 0); + signal accb: std_logic_vector(7 downto 0); + signal cc: std_logic_vector(7 downto 0); + signal cc_out: std_logic_vector(7 downto 0); + signal xreg: std_logic_vector(15 downto 0); + signal sp: std_logic_vector(15 downto 0); + signal ea: std_logic_vector(15 downto 0); + signal pc: std_logic_vector(15 downto 0); + signal md: std_logic_vector(15 downto 0); + signal left: std_logic_vector(15 downto 0); + signal right: std_logic_vector(15 downto 0); + signal out_alu: std_logic_vector(15 downto 0); + signal iv: std_logic_vector(1 downto 0); + signal nmi_req: std_logic; + signal nmi_ack: std_logic; + + signal state: state_type; + signal next_state: state_type; + signal pc_ctrl: pc_type; + signal ea_ctrl: ea_type; + signal op_ctrl: op_type; + signal md_ctrl: md_type; + signal acca_ctrl: acca_type; + signal accb_ctrl: accb_type; + signal ix_ctrl: ix_type; + signal cc_ctrl: cc_type; + signal sp_ctrl: sp_type; + signal iv_ctrl: iv_type; + signal left_ctrl: left_type; + signal right_ctrl: right_type; + signal alu_ctrl: alu_type; + signal addr_ctrl: addr_type; + signal dout_ctrl: dout_type; + signal nmi_ctrl: nmi_type; + + +begin + +---------------------------------- +-- +-- Address bus multiplexer +-- +---------------------------------- + +addr_mux: process( clk, addr_ctrl, pc, ea, sp, iv ) +begin + case addr_ctrl is + when idle_ad => + address <= "1111111111111111"; + vma <= '0'; + rw <= '1'; + when fetch_ad => + address <= pc; + vma <= '1'; + rw <= '1'; + when read_ad => + address <= ea; + vma <= '1'; + rw <= '1'; + when write_ad => + address <= ea; + vma <= '1'; + rw <= '0'; + when push_ad => + address <= sp; + vma <= '1'; + rw <= '0'; + when pull_ad => + address <= sp; + vma <= '1'; + rw <= '1'; + when int_hi_ad => + address <= "1111111111111" & iv & "0"; + vma <= '1'; + rw <= '1'; + when int_lo_ad => + address <= "1111111111111" & iv & "1"; + vma <= '1'; + rw <= '1'; + when others => + address <= "1111111111111111"; + vma <= '0'; + rw <= '1'; + end case; +end process; + +-------------------------------- +-- +-- Data Bus output +-- +-------------------------------- +dout_mux : process( clk, dout_ctrl, md, acca, accb, xreg, pc, cc ) +begin + case dout_ctrl is + when md_hi_dout => -- alu output + data_out <= md(15 downto 8); + when md_lo_dout => + data_out <= md(7 downto 0); + when acca_dout => -- accumulator a + data_out <= acca; + when accb_dout => -- accumulator b + data_out <= accb; + when ix_lo_dout => -- index reg + data_out <= xreg(7 downto 0); + when ix_hi_dout => -- index reg + data_out <= xreg(15 downto 8); + when cc_dout => -- condition codes + data_out <= cc; + when pc_lo_dout => -- low order pc + data_out <= pc(7 downto 0); + when pc_hi_dout => -- high order pc + data_out <= pc(15 downto 8); + when others => + data_out <= "00000000"; + end case; +end process; + + +---------------------------------- +-- +-- Program Counter Control +-- +---------------------------------- + +pc_mux: process( clk, pc_ctrl, pc, out_alu, data_in, ea, hold ) +variable tempof : std_logic_vector(15 downto 0); +variable temppc : std_logic_vector(15 downto 0); +begin + case pc_ctrl is + when add_ea_pc => + if ea(7) = '0' then + tempof := "00000000" & ea(7 downto 0); + else + tempof := "11111111" & ea(7 downto 0); + end if; + when inc_pc => + tempof := "0000000000000001"; + when others => + tempof := "0000000000000000"; + end case; + + case pc_ctrl is + when reset_pc => + temppc := "1111111111111110"; + when load_ea_pc => + temppc := ea; + when pull_lo_pc => + temppc(7 downto 0) := data_in; + temppc(15 downto 8) := pc(15 downto 8); + when pull_hi_pc => + temppc(7 downto 0) := pc(7 downto 0); + temppc(15 downto 8) := data_in; + when others => + temppc := pc; + end case; + + if clk'event and clk = '0' then + if hold = '1' then + pc <= pc; + else + pc <= temppc + tempof; + end if; + end if; +end process; + +---------------------------------- +-- +-- Effective Address Control +-- +---------------------------------- + +ea_mux: process( clk, ea_ctrl, ea, out_alu, data_in, accb, xreg, hold ) +variable tempind : std_logic_vector(15 downto 0); +variable tempea : std_logic_vector(15 downto 0); +begin + case ea_ctrl is + when add_ix_ea => + tempind := "00000000" & ea(7 downto 0); + when inc_ea => + tempind := "0000000000000001"; + when others => + tempind := "0000000000000000"; + end case; + + case ea_ctrl is + when reset_ea => + tempea := "0000000000000000"; + when load_accb_ea => + tempea := "00000000" & accb(7 downto 0); + when add_ix_ea => + tempea := xreg; + when fetch_first_ea => + tempea(7 downto 0) := data_in; + tempea(15 downto 8) := "00000000"; + when fetch_next_ea => + tempea(7 downto 0) := data_in; + tempea(15 downto 8) := ea(7 downto 0); + when others => + tempea := ea; + end case; + + if clk'event and clk = '0' then + if hold = '1' then + ea <= ea; + else + ea <= tempea + tempind; + end if; + end if; +end process; + +-------------------------------- +-- +-- Accumulator A +-- +-------------------------------- +acca_mux : process( clk, acca_ctrl, out_alu, acca, data_in, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + acca <= acca; + else + case acca_ctrl is + when reset_acca => + acca <= "00000000"; + when load_acca => + acca <= out_alu(7 downto 0); + when load_hi_acca => + acca <= out_alu(15 downto 8); + when pull_acca => + acca <= data_in; + when others => +-- when latch_acca => + acca <= acca; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- Accumulator B +-- +-------------------------------- +accb_mux : process( clk, accb_ctrl, out_alu, accb, data_in, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + accb <= accb; + else + case accb_ctrl is + when reset_accb => + accb <= "00000000"; + when load_accb => + accb <= out_alu(7 downto 0); + when pull_accb => + accb <= data_in; + when others => +-- when latch_accb => + accb <= accb; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- X Index register +-- +-------------------------------- +ix_mux : process( clk, ix_ctrl, out_alu, xreg, data_in, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + xreg <= xreg; + else + case ix_ctrl is + when reset_ix => + xreg <= "0000000000000000"; + when load_ix => + xreg <= out_alu(15 downto 0); + when pull_hi_ix => + xreg(15 downto 8) <= data_in; + when pull_lo_ix => + xreg(7 downto 0) <= data_in; + when others => +-- when latch_ix => + xreg <= xreg; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- stack pointer +-- +-------------------------------- +sp_mux : process( clk, sp_ctrl, out_alu, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + sp <= sp; + else + case sp_ctrl is + when reset_sp => + sp <= "0000000000000000"; + when load_sp => + sp <= out_alu(15 downto 0); + when others => +-- when latch_sp => + sp <= sp; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- Memory Data +-- +-------------------------------- +md_mux : process( clk, md_ctrl, out_alu, data_in, md, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + md <= md; + else + case md_ctrl is + when reset_md => + md <= "0000000000000000"; + when load_md => + md <= out_alu(15 downto 0); + when fetch_first_md => + md(15 downto 8) <= "00000000"; + md(7 downto 0) <= data_in; + when fetch_next_md => + md(15 downto 8) <= md(7 downto 0); + md(7 downto 0) <= data_in; + when shiftl_md => + md(15 downto 1) <= md(14 downto 0); + md(0) <= '0'; + when others => +-- when latch_md => + md <= md; + end case; + end if; + end if; +end process; + + +---------------------------------- +-- +-- Condition Codes +-- +---------------------------------- + +cc_mux: process( clk, cc_ctrl, cc_out, cc, data_in, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + cc <= cc; + else + case cc_ctrl is + when reset_cc => + cc <= "11000000"; + when load_cc => + cc <= cc_out; + when pull_cc => + cc <= data_in; + when others => +-- when latch_cc => + cc <= cc; + end case; + end if; + end if; +end process; + +---------------------------------- +-- +-- interrupt vector +-- +---------------------------------- + +iv_mux: process( clk, iv_ctrl, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + iv <= iv; + else + case iv_ctrl is + when reset_iv => + iv <= "11"; + when nmi_iv => + iv <= "10"; + when swi_iv => + iv <= "01"; + when irq_iv => + iv <= "00"; + when others => + iv <= iv; + end case; + end if; + end if; +end process; + +---------------------------------- +-- +-- op code fetch +-- +---------------------------------- + +op_fetch: process( clk, data_in, op_ctrl, op_code, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + op_code <= op_code; + else + case op_ctrl is + when reset_op => + op_code <= "00000001"; -- nop + when fetch_op => + op_code <= data_in; + when others => +-- when latch_op => + op_code <= op_code; + end case; + end if; + end if; +end process; + +---------------------------------- +-- +-- Left Mux +-- +---------------------------------- + +left_mux: process( left_ctrl, acca, accb, xreg, sp, pc, ea, md ) +begin + case left_ctrl is + when acca_left => + left(15 downto 8) <= "00000000"; + left(7 downto 0) <= acca; + when accb_left => + left(15 downto 8) <= "00000000"; + left(7 downto 0) <= accb; + when accd_left => + left(15 downto 8) <= acca; + left(7 downto 0) <= accb; + when ix_left => + left <= xreg; + when sp_left => + left <= sp; + when others => +-- when md_left => + left <= md; + end case; +end process; +---------------------------------- +-- +-- Right Mux +-- +---------------------------------- + +right_mux: process( right_ctrl, data_in, md, accb, ea ) +begin + case right_ctrl is + when zero_right => + right <= "0000000000000000"; + when plus_one_right => + right <= "0000000000000001"; + when accb_right => + right <= "00000000" & accb; + when others => +-- when md_right => + right <= md; + end case; +end process; + +---------------------------------- +-- +-- Arithmetic Logic Unit +-- +---------------------------------- + +mux_alu: process( alu_ctrl, cc, left, right, out_alu, cc_out ) +variable valid_lo, valid_hi : boolean; +variable carry_in : std_logic; +variable daa_reg : std_logic_vector(7 downto 0); +begin + + case alu_ctrl is + when alu_adc | alu_sbc | + alu_rol8 | alu_ror8 => + carry_in := cc(CBIT); + when others => + carry_in := '0'; + end case; + + valid_lo := left(3 downto 0) <= 9; + valid_hi := left(7 downto 4) <= 9; + + if (cc(CBIT) = '0') then + if( cc(HBIT) = '1' ) then + if valid_hi then + daa_reg := "00000110"; + else + daa_reg := "01100110"; + end if; + else + if valid_lo then + if valid_hi then + daa_reg := "00000000"; + else + daa_reg := "01100000"; + end if; + else + if( left(7 downto 4) <= 8 ) then + daa_reg := "00000110"; + else + daa_reg := "01100110"; + end if; + end if; + end if; + else + if ( cc(HBIT) = '1' )then + daa_reg := "01100110"; + else + if valid_lo then + daa_reg := "01100000"; + else + daa_reg := "01100110"; + end if; + end if; + end if; + + case alu_ctrl is + when alu_add8 | alu_inc | + alu_add16 | alu_inx | + alu_adc => + out_alu <= left + right + ("000000000000000" & carry_in); + when alu_sub8 | alu_dec | + alu_sub16 | alu_dex | + alu_sbc | alu_cpx => + out_alu <= left - right - ("000000000000000" & carry_in); + when alu_and => + out_alu <= left and right; -- and/bit + when alu_ora => + out_alu <= left or right; -- or + when alu_eor => + out_alu <= left xor right; -- eor/xor + when alu_lsl16 | alu_asl8 | alu_rol8 => + out_alu <= left(14 downto 0) & carry_in; -- rol8/asl8/lsl16 + when alu_lsr16 | alu_lsr8 => + out_alu <= carry_in & left(15 downto 1); -- lsr + when alu_ror8 => + out_alu <= "00000000" & carry_in & left(7 downto 1); -- ror + when alu_asr8 => + out_alu <= "00000000" & left(7) & left(7 downto 1); -- asr + when alu_neg => + out_alu <= right - left; -- neg (right=0) + when alu_com => + out_alu <= not left; + when alu_clr | alu_ld8 | alu_ld16 => + out_alu <= right; -- clr, ld + when alu_st8 | alu_st16 => + out_alu <= left; + when alu_daa => + out_alu <= left + ("00000000" & daa_reg); + when alu_tpa => + out_alu <= "00000000" & cc; + when others => + out_alu <= left; -- nop + end case; + + -- + -- carry bit + -- + case alu_ctrl is + when alu_add8 | alu_adc => + cc_out(CBIT) <= (left(7) and right(7)) or + (left(7) and not out_alu(7)) or + (right(7) and not out_alu(7)); + when alu_sub8 | alu_sbc => + cc_out(CBIT) <= ((not left(7)) and right(7)) or + ((not left(7)) and out_alu(7)) or + (right(7) and out_alu(7)); + when alu_add16 => + cc_out(CBIT) <= (left(15) and right(15)) or + (left(15) and not out_alu(15)) or + (right(15) and not out_alu(15)); + when alu_sub16 => + cc_out(CBIT) <= ((not left(15)) and right(15)) or + ((not left(15)) and out_alu(15)) or + (right(15) and out_alu(15)); + when alu_ror8 | alu_lsr16 | alu_lsr8 | alu_asr8 => + cc_out(CBIT) <= left(0); + when alu_rol8 | alu_asl8 => + cc_out(CBIT) <= left(7); + when alu_lsl16 => + cc_out(CBIT) <= left(15); + when alu_com => + cc_out(CBIT) <= '1'; + when alu_neg | alu_clr => + cc_out(CBIT) <= out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or + out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0); + when alu_daa => + if ( daa_reg(7 downto 4) = "0110" ) then + cc_out(CBIT) <= '1'; + else + cc_out(CBIT) <= '0'; + end if; + when alu_sec => + cc_out(CBIT) <= '1'; + when alu_clc => + cc_out(CBIT) <= '0'; + when alu_tap => + cc_out(CBIT) <= left(CBIT); + when others => -- carry is not affected by cpx + cc_out(CBIT) <= cc(CBIT); + end case; + -- + -- Zero flag + -- + case alu_ctrl is + when alu_add8 | alu_sub8 | + alu_adc | alu_sbc | + alu_and | alu_ora | alu_eor | + alu_inc | alu_dec | + alu_neg | alu_com | alu_clr | + alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 | + alu_ld8 | alu_st8 => + cc_out(ZBIT) <= not( out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or + out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0) ); + when alu_add16 | alu_sub16 | + alu_lsl16 | alu_lsr16 | + alu_inx | alu_dex | + alu_ld16 | alu_st16 | alu_cpx => + cc_out(ZBIT) <= not( out_alu(15) or out_alu(14) or out_alu(13) or out_alu(12) or + out_alu(11) or out_alu(10) or out_alu(9) or out_alu(8) or + out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or + out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0) ); + when alu_tap => + cc_out(ZBIT) <= left(ZBIT); + when others => + cc_out(ZBIT) <= cc(ZBIT); + end case; + + -- + -- negative flag + -- + case alu_ctrl is + when alu_add8 | alu_sub8 | + alu_adc | alu_sbc | + alu_and | alu_ora | alu_eor | + alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 | + alu_inc | alu_dec | alu_neg | alu_com | alu_clr | + alu_ld8 | alu_st8 => + cc_out(NBIT) <= out_alu(7); + when alu_add16 | alu_sub16 | + alu_lsl16 | alu_lsr16 | + alu_ld16 | alu_st16 | alu_cpx => + cc_out(NBIT) <= out_alu(15); + when alu_tap => + cc_out(NBIT) <= left(NBIT); + when others => + cc_out(NBIT) <= cc(NBIT); + end case; + + -- + -- Interrupt mask flag + -- + case alu_ctrl is + when alu_sei => + cc_out(IBIT) <= '1'; -- set interrupt mask + when alu_cli => + cc_out(IBIT) <= '0'; -- clear interrupt mask + when alu_tap => + cc_out(IBIT) <= left(IBIT); + when others => + cc_out(IBIT) <= cc(IBIT); -- interrupt mask + end case; + + -- + -- Half Carry flag + -- + case alu_ctrl is + when alu_add8 | alu_adc => + cc_out(HBIT) <= (left(3) and right(3)) or + (right(3) and not out_alu(3)) or + (left(3) and not out_alu(3)); + when alu_tap => + cc_out(HBIT) <= left(HBIT); + when others => + cc_out(HBIT) <= cc(HBIT); + end case; + + -- + -- Overflow flag + -- + case alu_ctrl is + when alu_add8 | alu_adc => + cc_out(VBIT) <= (left(7) and right(7) and (not out_alu(7))) or + ((not left(7)) and (not right(7)) and out_alu(7)); + when alu_sub8 | alu_sbc => + cc_out(VBIT) <= (left(7) and (not right(7)) and (not out_alu(7))) or + ((not left(7)) and right(7) and out_alu(7)); + when alu_add16 => + cc_out(VBIT) <= (left(15) and right(15) and (not out_alu(15))) or + ((not left(15)) and (not right(15)) and out_alu(15)); + when alu_sub16 | alu_cpx => + cc_out(VBIT) <= (left(15) and (not right(15)) and (not out_alu(15))) or + ((not left(15)) and right(15) and out_alu(15)); + when alu_inc => + cc_out(VBIT) <= ((not left(7)) and left(6) and left(5) and left(4) and + left(3) and left(2) and left(1) and left(0)); + when alu_dec | alu_neg => + cc_out(VBIT) <= (left(7) and (not left(6)) and (not left(5)) and (not left(4)) and + (not left(3)) and (not left(2)) and (not left(1)) and (not left(0))); + when alu_asr8 => + cc_out(VBIT) <= left(0) xor left(7); + when alu_lsr8 | alu_lsr16 => + cc_out(VBIT) <= left(0); + when alu_ror8 => + cc_out(VBIT) <= left(0) xor cc(CBIT); + when alu_lsl16 => + cc_out(VBIT) <= left(15) xor left(14); + when alu_rol8 | alu_asl8 => + cc_out(VBIT) <= left(7) xor left(6); + when alu_tap => + cc_out(VBIT) <= left(VBIT); + when alu_and | alu_ora | alu_eor | alu_com | + alu_st8 | alu_st16 | alu_ld8 | alu_ld16 | + alu_clv => + cc_out(VBIT) <= '0'; + when alu_sev => + cc_out(VBIT) <= '1'; + when others => + cc_out(VBIT) <= cc(VBIT); + end case; + + case alu_ctrl is + when alu_tap => + cc_out(XBIT) <= cc(XBIT) and left(XBIT); + cc_out(SBIT) <= left(SBIT); + when others => + cc_out(XBIT) <= cc(XBIT) and left(XBIT); + cc_out(SBIT) <= cc(SBIT); + end case; + + test_alu <= out_alu; + test_cc <= cc_out; +end process; + +------------------------------------ +-- +-- Detect Edge of NMI interrupt +-- +------------------------------------ + +nmi_handler : process( clk, rst, nmi, nmi_ack ) +begin + if clk'event and clk='0' then + if hold = '1' then + nmi_req <= nmi_req; + else + if rst='1' then + nmi_req <= '0'; + else + if (nmi='1') and (nmi_ack='0') then + nmi_req <= '1'; + else + if (nmi='0') and (nmi_ack='1') then + nmi_req <= '0'; + else + nmi_req <= nmi_req; + end if; + end if; + end if; + end if; + end if; +end process; + +------------------------------------ +-- +-- Nmi mux +-- +------------------------------------ + +nmi_mux: process( clk, nmi_ctrl, nmi_ack, hold ) +begin + if clk'event and clk='0' then + if hold = '1' then + nmi_ack <= nmi_ack; + else + case nmi_ctrl is + when set_nmi => + nmi_ack <= '1'; + when reset_nmi => + nmi_ack <= '0'; + when others => +-- when latch_nmi => + nmi_ack <= nmi_ack; + end case; + end if; + end if; +end process; + +------------------------------------ +-- +-- state sequencer +-- +------------------------------------ +process( state, op_code, cc, ea, irq, nmi_req, nmi_ack, hold, halt ) + begin + case state is + when reset_state => -- released from reset + -- reset the registers + op_ctrl <= reset_op; + acca_ctrl <= reset_acca; + accb_ctrl <= reset_accb; + ix_ctrl <= reset_ix; + sp_ctrl <= reset_sp; + pc_ctrl <= reset_pc; + ea_ctrl <= reset_ea; + md_ctrl <= reset_md; + iv_ctrl <= reset_iv; + nmi_ctrl <= reset_nmi; + -- idle the ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= reset_cc; + -- idle the bus + dout_ctrl <= md_lo_dout; + addr_ctrl <= idle_ad; + next_state <= vect_hi_state; + + -- + -- Jump via interrupt vector + -- iv holds interrupt type + -- fetch PC hi from vector location + -- + when vect_hi_state => + -- default the registers + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + md_ctrl <= latch_md; + ea_ctrl <= latch_ea; + iv_ctrl <= latch_iv; + -- idle the ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- fetch pc low interrupt vector + pc_ctrl <= pull_hi_pc; + addr_ctrl <= int_hi_ad; + dout_ctrl <= pc_hi_dout; + next_state <= vect_lo_state; + -- + -- jump via interrupt vector + -- iv holds vector type + -- fetch PC lo from vector location + -- + when vect_lo_state => + -- default the registers + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + md_ctrl <= latch_md; + ea_ctrl <= latch_ea; + iv_ctrl <= latch_iv; + -- idle the ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- fetch the vector low byte + pc_ctrl <= pull_lo_pc; + addr_ctrl <= int_lo_ad; + dout_ctrl <= pc_lo_dout; + next_state <= fetch_state; + + -- + -- Here to fetch an instruction + -- PC points to opcode + -- Should service interrupt requests at this point + -- either from the timer + -- or from the external input. + -- + when fetch_state => + case op_code(7 downto 4) is + when "0000" | + "0001" | + "0010" | -- branch conditional + "0011" | + "0100" | -- acca single op + "0101" | -- accb single op + "0110" | -- indexed single op + "0111" => -- extended single op + -- idle ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + + when "1000" | -- acca immediate + "1001" | -- acca direct + "1010" | -- acca indexed + "1011" => -- acca extended + case op_code(3 downto 0) is + when "0000" => -- suba + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0001" => -- cmpa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0010" => -- sbca + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sbc; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0011" => -- subd + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0100" => -- anda + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0101" => -- bita + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0110" => -- ldaa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0111" => -- staa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1000" => -- eora + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_eor; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1001" => -- adca + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_adc; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1010" => -- oraa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ora; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1011" => -- adda + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1100" => -- cpx + left_ctrl <= ix_left; + right_ctrl <= md_right; + alu_ctrl <= alu_cpx; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1101" => -- bsr / jsr + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1110" => -- lds + left_ctrl <= sp_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + when "1111" => -- sts + left_ctrl <= sp_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st16; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when others => + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + end case; + when "1100" | -- accb immediate + "1101" | -- accb direct + "1110" | -- accb indexed + "1111" => -- accb extended + case op_code(3 downto 0) is + when "0000" => -- subb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0001" => -- cmpb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0010" => -- sbcb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sbc; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0011" => -- addd + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0100" => -- andb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0101" => -- bitb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0110" => -- ldab + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0111" => -- stab + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1000" => -- eorb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_eor; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1001" => -- adcb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_adc; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1010" => -- orab + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ora; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1011" => -- addb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1100" => -- ldd + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1101" => -- std + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st16; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1110" => -- ldx + left_ctrl <= ix_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= load_ix; + sp_ctrl <= latch_sp; + when "1111" => -- stx + left_ctrl <= ix_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st16; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when others => + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + end case; + when others => + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + end case; + md_ctrl <= latch_md; + -- fetch the op code + op_ctrl <= fetch_op; + ea_ctrl <= reset_ea; + addr_ctrl <= fetch_ad; + dout_ctrl <= md_lo_dout; + iv_ctrl <= latch_iv; + if halt = '1' then + pc_ctrl <= latch_pc; + nmi_ctrl <= latch_nmi; + next_state <= halt_state; + -- service non maskable interrupts + elsif (nmi_req = '1') and (nmi_ack = '0') then + pc_ctrl <= latch_pc; + nmi_ctrl <= set_nmi; + next_state <= int_pcl_state; + -- service maskable interrupts + else + -- + -- nmi request is not cleared until nmi input goes low + -- + if(nmi_req = '0') and (nmi_ack='1') then + nmi_ctrl <= reset_nmi; + else + nmi_ctrl <= latch_nmi; + end if; + -- + -- IRQ is level sensitive + -- + if (irq = '1') and (cc(IBIT) = '0') then + pc_ctrl <= latch_pc; + next_state <= int_pcl_state; + else + -- Advance the PC to fetch next instruction byte + pc_ctrl <= inc_pc; + next_state <= decode_state; + end if; + end if; + -- + -- Here to decode instruction + -- and fetch next byte of intruction + -- whether it be necessary or not + -- + when decode_state => + -- fetch first byte of address or immediate data + ea_ctrl <= fetch_first_ea; + addr_ctrl <= fetch_ad; + dout_ctrl <= md_lo_dout; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + iv_ctrl <= latch_iv; + case op_code(7 downto 4) is + when "0000" => + md_ctrl <= fetch_first_md; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + case op_code(3 downto 0) is + when "0001" => -- nop + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "0100" => -- lsrd + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_lsr16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + when "0101" => -- lsld + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_lsl16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + when "0110" => -- tap + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_tap; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "0111" => -- tpa + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_tpa; + cc_ctrl <= latch_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1000" => -- inx + left_ctrl <= ix_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_inx; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= load_ix; + when "1001" => -- dex + left_ctrl <= ix_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_dex; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= load_ix; + when "1010" => -- clv + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_clv; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1011" => -- sev + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_sev; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1100" => -- clc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_clc; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1101" => -- sec + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_sec; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1110" => -- cli + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_cli; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1111" => -- sei + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_sei; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + end case; + next_state <= fetch_state; + -- acca / accb inherent instructions + when "0001" => + md_ctrl <= fetch_first_md; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + left_ctrl <= acca_left; + right_ctrl <= accb_right; + case op_code(3 downto 0) is + when "0000" => -- sba + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + when "0001" => -- cba + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + when "0110" => -- tab + alu_ctrl <= alu_st8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + when "0111" => -- tba + alu_ctrl <= alu_ld8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + when "1001" => -- daa + alu_ctrl <= alu_daa; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + when "1011" => -- aba + alu_ctrl <= alu_add8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + when others => + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end case; + next_state <= fetch_state; + when "0010" => -- branch conditional + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- increment the pc + pc_ctrl <= inc_pc; + case op_code(3 downto 0) is + when "0000" => -- bra + next_state <= branch_state; + when "0001" => -- brn + next_state <= fetch_state; + when "0010" => -- bhi + if (cc(CBIT) or cc(ZBIT)) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "0011" => -- bls + if (cc(CBIT) or cc(ZBIT)) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "0100" => -- bcc/bhs + if cc(CBIT) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "0101" => -- bcs/blo + if cc(CBIT) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "0110" => -- bne + if cc(ZBIT) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "0111" => -- beq + if cc(ZBIT) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1000" => -- bvc + if cc(VBIT) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1001" => -- bvs + if cc(VBIT) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1010" => -- bpl + if cc(NBIT) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1011" => -- bmi + if cc(NBIT) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1100" => -- bge + if (cc(NBIT) xor cc(VBIT)) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1101" => -- blt + if (cc(NBIT) xor cc(VBIT)) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1110" => -- bgt + if (cc(ZBIT) or (cc(NBIT) xor cc(VBIT))) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1111" => -- ble + if (cc(ZBIT) or (cc(NBIT) xor cc(VBIT))) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when others => + next_state <= fetch_state; + end case; + -- + -- Single byte stack operators + -- Do not advance PC + -- + when "0011" => + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + case op_code(3 downto 0) is + when "0000" => -- tsx + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= load_ix; + sp_ctrl <= latch_sp; + next_state <= fetch_state; + when "0001" => -- ins + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= fetch_state; + when "0010" => -- pula + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= pula_state; + when "0011" => -- pulb + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= pulb_state; + when "0100" => -- des + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= fetch_state; + when "0101" => -- txs + left_ctrl <= ix_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= fetch_state; + when "0110" => -- psha + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= psha_state; + when "0111" => -- pshb + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= pshb_state; + when "1000" => -- pulx + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= pulx_hi_state; + when "1001" => -- rts + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= rts_hi_state; + when "1010" => -- abx + left_ctrl <= ix_left; + right_ctrl <= accb_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= load_ix; + sp_ctrl <= latch_sp; + next_state <= fetch_state; + when "1011" => -- rti + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= rti_cc_state; + when "1100" => -- pshx + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= pshx_lo_state; + when "1101" => -- mul + left_ctrl <= acca_left; + right_ctrl <= accb_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= mul_state; + when "1110" => -- wai + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= int_pcl_state; + when "1111" => -- swi + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= int_pcl_state; + when others => + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= fetch_state; + end case; + -- + -- Accumulator A Single operand + -- source = Acc A dest = Acc A + -- Do not advance PC + -- + when "0100" => -- acca single op + md_ctrl <= fetch_first_md; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + left_ctrl <= acca_left; + case op_code(3 downto 0) is + when "0000" => -- neg + right_ctrl <= zero_right; + alu_ctrl <= alu_neg; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "0011" => -- com + right_ctrl <= zero_right; + alu_ctrl <= alu_com; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "0100" => -- lsr + right_ctrl <= zero_right; + alu_ctrl <= alu_lsr8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "0110" => -- ror + right_ctrl <= zero_right; + alu_ctrl <= alu_ror8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "0111" => -- asr + right_ctrl <= zero_right; + alu_ctrl <= alu_asr8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "1000" => -- asl + right_ctrl <= zero_right; + alu_ctrl <= alu_asl8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "1001" => -- rol + right_ctrl <= zero_right; + alu_ctrl <= alu_rol8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "1010" => -- dec + right_ctrl <= plus_one_right; + alu_ctrl <= alu_dec; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "1011" => -- undefined + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + acca_ctrl <= latch_acca; + cc_ctrl <= latch_cc; + when "1100" => -- inc + right_ctrl <= plus_one_right; + alu_ctrl <= alu_inc; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "1101" => -- tst + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + acca_ctrl <= latch_acca; + cc_ctrl <= load_cc; + when "1110" => -- jmp + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + acca_ctrl <= latch_acca; + cc_ctrl <= latch_cc; + when "1111" => -- clr + right_ctrl <= zero_right; + alu_ctrl <= alu_clr; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when others => + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + acca_ctrl <= latch_acca; + cc_ctrl <= latch_cc; + end case; + next_state <= fetch_state; + -- + -- single operand acc b + -- Do not advance PC + -- + when "0101" => + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + pc_ctrl <= latch_pc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + left_ctrl <= accb_left; + case op_code(3 downto 0) is + when "0000" => -- neg + right_ctrl <= zero_right; + alu_ctrl <= alu_neg; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "0011" => -- com + right_ctrl <= zero_right; + alu_ctrl <= alu_com; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "0100" => -- lsr + right_ctrl <= zero_right; + alu_ctrl <= alu_lsr8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "0110" => -- ror + right_ctrl <= zero_right; + alu_ctrl <= alu_ror8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "0111" => -- asr + right_ctrl <= zero_right; + alu_ctrl <= alu_asr8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "1000" => -- asl + right_ctrl <= zero_right; + alu_ctrl <= alu_asl8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "1001" => -- rol + right_ctrl <= zero_right; + alu_ctrl <= alu_rol8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "1010" => -- dec + right_ctrl <= plus_one_right; + alu_ctrl <= alu_dec; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "1011" => -- undefined + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + accb_ctrl <= latch_accb; + cc_ctrl <= latch_cc; + when "1100" => -- inc + right_ctrl <= plus_one_right; + alu_ctrl <= alu_inc; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "1101" => -- tst + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + accb_ctrl <= latch_accb; + cc_ctrl <= load_cc; + when "1110" => -- jmp + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + accb_ctrl <= latch_accb; + cc_ctrl <= latch_cc; + when "1111" => -- clr + right_ctrl <= zero_right; + alu_ctrl <= alu_clr; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when others => + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + accb_ctrl <= latch_accb; + cc_ctrl <= latch_cc; + end case; + next_state <= fetch_state; + -- + -- Single operand indexed + -- Two byte instruction so advance PC + -- EA should hold index offset + -- + when "0110" => -- indexed single op + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= indexed_state; + -- + -- Single operand extended addressing + -- three byte instruction so advance the PC + -- Low order EA holds high order address + -- + when "0111" => -- extended single op + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= extended_state; + + when "1000" => -- acca immediate + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + case op_code(3 downto 0) is + when "0011" | -- subdd # + "1100" | -- cpx # + "1110" => -- lds # + next_state <= immediate16_state; + when "1101" => -- bsr + next_state <= bsr_state; + when others => + next_state <= fetch_state; + end case; + + when "1001" => -- acca direct + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + pc_ctrl <= inc_pc; + case op_code(3 downto 0) is + when "0111" => -- staa direct + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1111" => -- sts direct + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when "1101" => -- jsr direct + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + next_state <= jsr_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + next_state <= read8_state; + end case; + + when "1010" => -- acca indexed + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= indexed_state; + + when "1011" => -- acca extended + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= extended_state; + + when "1100" => -- accb immediate + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + case op_code(3 downto 0) is + when "0011" | -- addd # + "1100" | -- ldd # + "1110" => -- ldx # + next_state <= immediate16_state; + when others => + next_state <= fetch_state; + end case; + + when "1101" => -- accb direct + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + pc_ctrl <= inc_pc; + case op_code(3 downto 0) is + when "0111" => -- stab direct + left_ctrl <= accb_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- std direct + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when "1111" => -- stx direct + left_ctrl <= ix_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + next_state <= read8_state; + end case; + + when "1110" => -- accb indexed + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= indexed_state; + + when "1111" => -- accb extended + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= extended_state; + + when others => + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- idle the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= latch_pc; + next_state <= fetch_state; + end case; + + when immediate16_state => + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + op_ctrl <= latch_op; + iv_ctrl <= latch_iv; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + -- fetch next immediate byte + md_ctrl <= fetch_next_md; + addr_ctrl <= fetch_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + -- + -- ea holds 8 bit index offet + -- calculate the effective memory address + -- using the alu + -- + when indexed_state => + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + -- calculate effective address from index reg + -- index offest is not sign extended + ea_ctrl <= add_ix_ea; + -- idle the bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + -- work out next state + case op_code(7 downto 4) is + when "0110" => -- single op indexed + md_ctrl <= latch_md; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + case op_code(3 downto 0) is + when "1011" => -- undefined + next_state <= fetch_state; + when "1110" => -- jmp + next_state <= jmp_state; + when others => + next_state <= read8_state; + end case; + when "1010" => -- acca indexed + case op_code(3 downto 0) is + when "0111" => -- staa + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- jsr + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= jsr_state; + when "1111" => -- sts + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= read8_state; + end case; + when "1110" => -- accb indexed + case op_code(3 downto 0) is + when "0111" => -- stab direct + left_ctrl <= accb_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- std direct + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when "1111" => -- stx direct + left_ctrl <= ix_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= read8_state; + end case; + when others => + md_ctrl <= latch_md; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + next_state <= fetch_state; + end case; + -- + -- ea holds the low byte of the absolute address + -- Move ea low byte into ea high byte + -- load new ea low byte to for absolute 16 bit address + -- advance the program counter + -- + when extended_state => -- fetch ea low byte + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + -- increment pc + pc_ctrl <= inc_pc; + -- fetch next effective address bytes + ea_ctrl <= fetch_next_ea; + addr_ctrl <= fetch_ad; + dout_ctrl <= md_lo_dout; + -- work out the next state + case op_code(7 downto 4) is + when "0111" => -- single op extended + md_ctrl <= latch_md; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + case op_code(3 downto 0) is + when "1011" => -- undefined + next_state <= fetch_state; + when "1110" => -- jmp + next_state <= jmp_state; + when others => + next_state <= read8_state; + end case; + when "1011" => -- acca extended + case op_code(3 downto 0) is + when "0111" => -- staa + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- jsr + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= jsr_state; + when "1111" => -- sts + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= read8_state; + end case; + when "1111" => -- accb extended + case op_code(3 downto 0) is + when "0111" => -- stab + left_ctrl <= accb_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- std + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when "1111" => -- stx + left_ctrl <= ix_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= read8_state; + end case; + when others => + md_ctrl <= latch_md; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + next_state <= fetch_state; + end case; + -- + -- here if ea holds low byte (direct page) + -- can enter here from extended addressing + -- read memory location + -- note that reads may be 8 or 16 bits + -- + when read8_state => -- read data + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + -- + addr_ctrl <= read_ad; + dout_ctrl <= md_lo_dout; + case op_code(7 downto 4) is + when "0110" | "0111" => -- single operand + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + ea_ctrl <= latch_ea; + next_state <= execute_state; + + when "1001" | "1010" | "1011" => -- acca + case op_code(3 downto 0) is + when "0011" | -- subd + "1110" | -- lds + "1100" => -- cpx + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + -- increment the effective address in case of 16 bit load + ea_ctrl <= inc_ea; + next_state <= read16_state; +-- when "0111" => -- staa +-- left_ctrl <= acca_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_st8; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= load_md; +-- ea_ctrl <= latch_ea; +-- next_state <= write8_state; +-- when "1101" => -- jsr +-- left_ctrl <= acca_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_nop; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= latch_md; +-- ea_ctrl <= latch_ea; +-- next_state <= jsr_state; +-- when "1111" => -- sts +-- left_ctrl <= sp_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_st16; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= load_md; +-- ea_ctrl <= latch_ea; +-- next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + ea_ctrl <= latch_ea; + next_state <= fetch_state; + end case; + + when "1101" | "1110" | "1111" => -- accb + case op_code(3 downto 0) is + when "0011" | -- addd + "1100" | -- ldd + "1110" => -- ldx + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + -- increment the effective address in case of 16 bit load + ea_ctrl <= inc_ea; + next_state <= read16_state; +-- when "0111" => -- stab +-- left_ctrl <= accb_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_st8; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= load_md; +-- ea_ctrl <= latch_ea; +-- next_state <= write8_state; +-- when "1101" => -- std +-- left_ctrl <= accd_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_st16; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= load_md; +-- ea_ctrl <= latch_ea; +-- next_state <= write16_state; +-- when "1111" => -- stx +-- left_ctrl <= ix_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_st16; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= load_md; +-- ea_ctrl <= latch_ea; +-- next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + ea_ctrl <= latch_ea; + next_state <= execute_state; + end case; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + ea_ctrl <= latch_ea; + next_state <= fetch_state; + end case; + + when read16_state => -- read second data byte from ea + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- idle the effective address + ea_ctrl <= latch_ea; + -- read the low byte of the 16 bit data + md_ctrl <= fetch_next_md; + addr_ctrl <= read_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + -- + -- 16 bit Write state + -- write high byte of ALU output. + -- EA hold address of memory to write to + -- Advance the effective address in ALU + -- + when write16_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + -- increment the effective address + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ea_ctrl <= inc_ea; + -- write the ALU hi byte to ea + addr_ctrl <= write_ad; + dout_ctrl <= md_hi_dout; + next_state <= write8_state; + -- + -- 8 bit write + -- Write low 8 bits of ALU output + -- + when write8_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle the ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- write ALU low byte output + addr_ctrl <= write_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + + when jmp_state => + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- load PC with effective address + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= load_ea_pc; + -- idle the bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + + when jsr_state => -- JSR + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc low + addr_ctrl <= push_ad; + dout_ctrl <= pc_lo_dout; + next_state <= jsr1_state; + + when jsr1_state => -- JSR + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc hi + addr_ctrl <= push_ad; + dout_ctrl <= pc_hi_dout; + next_state <= jmp_state; + + when branch_state => -- Bcc + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- calculate signed branch + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= add_ea_pc; + -- idle the bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + + when bsr_state => -- BSR + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc low + addr_ctrl <= push_ad; + dout_ctrl <= pc_lo_dout; + next_state <= bsr1_state; + + when bsr1_state => -- BSR + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc hi + addr_ctrl <= push_ad; + dout_ctrl <= pc_hi_dout; + next_state <= branch_state; + + when rts_hi_state => -- RTS + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment the sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- read pc hi + pc_ctrl <= pull_hi_pc; + addr_ctrl <= pull_ad; + dout_ctrl <= pc_hi_dout; + next_state <= rts_lo_state; + + when rts_lo_state => -- RTS1 + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle the ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- read pc low + pc_ctrl <= pull_lo_pc; + addr_ctrl <= pull_ad; + dout_ctrl <= pc_lo_dout; + next_state <= fetch_state; + + when mul_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- move acca to md + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mulea_state; + + when mulea_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + md_ctrl <= latch_md; + -- idle ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- move accb to ea + ea_ctrl <= load_accb_ea; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= muld_state; + + when muld_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + md_ctrl <= latch_md; + -- clear accd + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_ld8; + cc_ctrl <= latch_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul0_state; + + when mul0_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 0 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(0) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul1_state; + + when mul1_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 1 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(1) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul2_state; + + when mul2_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 2 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(2) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul3_state; + + when mul3_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 3 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(3) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul4_state; + + when mul4_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 4 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(4) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul5_state; + + when mul5_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 5 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(5) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul6_state; + + when mul6_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 6 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(6) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul7_state; + + when mul7_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 7 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(7) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + + when execute_state => -- execute single operand instruction + -- default + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + case op_code(7 downto 4) is + when "0110" | -- indexed single op + "0111" => -- extended single op + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + ea_ctrl <= latch_ea; + -- idle the bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + left_ctrl <= md_left; + case op_code(3 downto 0) is + when "0000" => -- neg + right_ctrl <= zero_right; + alu_ctrl <= alu_neg; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "0011" => -- com + right_ctrl <= zero_right; + alu_ctrl <= alu_com; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "0100" => -- lsr + right_ctrl <= zero_right; + alu_ctrl <= alu_lsr8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "0110" => -- ror + right_ctrl <= zero_right; + alu_ctrl <= alu_ror8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "0111" => -- asr + right_ctrl <= zero_right; + alu_ctrl <= alu_asr8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1000" => -- asl + right_ctrl <= zero_right; + alu_ctrl <= alu_asl8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1001" => -- rol + right_ctrl <= zero_right; + alu_ctrl <= alu_rol8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1010" => -- dec + right_ctrl <= plus_one_right; + alu_ctrl <= alu_dec; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1011" => -- undefined + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= fetch_state; + when "1100" => -- inc + right_ctrl <= plus_one_right; + alu_ctrl <= alu_inc; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- tst + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= load_cc; + md_ctrl <= latch_md; + next_state <= fetch_state; + when "1110" => -- jmp + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= fetch_state; + when "1111" => -- clr + right_ctrl <= zero_right; + alu_ctrl <= alu_clr; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when others => + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= fetch_state; + end case; + + when others => + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + ea_ctrl <= latch_ea; + -- idle the bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + end case; + + when psha_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write acca + addr_ctrl <= push_ad; + dout_ctrl <= acca_dout; + next_state <= fetch_state; + + when pula_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle sp + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + sp_ctrl <= latch_sp; + -- read acca + acca_ctrl <= pull_acca; + addr_ctrl <= pull_ad; + dout_ctrl <= acca_dout; + next_state <= fetch_state; + + when pshb_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write accb + addr_ctrl <= push_ad; + dout_ctrl <= accb_dout; + next_state <= fetch_state; + + when pulb_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle sp + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + sp_ctrl <= latch_sp; + -- read accb + accb_ctrl <= pull_accb; + addr_ctrl <= pull_ad; + dout_ctrl <= accb_dout; + next_state <= fetch_state; + + when pshx_lo_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write ix low + addr_ctrl <= push_ad; + dout_ctrl <= ix_lo_dout; + next_state <= pshx_hi_state; + + when pshx_hi_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write ix hi + addr_ctrl <= push_ad; + dout_ctrl <= ix_hi_dout; + next_state <= fetch_state; + + when pulx_hi_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- pull ix hi + ix_ctrl <= pull_hi_ix; + addr_ctrl <= pull_ad; + dout_ctrl <= ix_hi_dout; + next_state <= pulx_lo_state; + + when pulx_lo_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle sp + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + sp_ctrl <= latch_sp; + -- read ix low + ix_ctrl <= pull_lo_ix; + addr_ctrl <= pull_ad; + dout_ctrl <= ix_lo_dout; + next_state <= fetch_state; + + -- + -- return from interrupt + -- enter here from bogus interrupts + -- + when rti_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- idle address bus + cc_ctrl <= latch_cc; + addr_ctrl <= idle_ad; + dout_ctrl <= cc_dout; + next_state <= rti_cc_state; + + when rti_cc_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read cc + cc_ctrl <= pull_cc; + addr_ctrl <= pull_ad; + dout_ctrl <= cc_dout; + next_state <= rti_accb_state; + + when rti_accb_state => + -- default registers + acca_ctrl <= latch_acca; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- read accb + accb_ctrl <= pull_accb; + addr_ctrl <= pull_ad; + dout_ctrl <= accb_dout; + next_state <= rti_acca_state; + + when rti_acca_state => + -- default registers + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- read acca + acca_ctrl <= pull_acca; + addr_ctrl <= pull_ad; + dout_ctrl <= acca_dout; + next_state <= rti_ixh_state; + + when rti_ixh_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- read ix hi + ix_ctrl <= pull_hi_ix; + addr_ctrl <= pull_ad; + dout_ctrl <= ix_hi_dout; + next_state <= rti_ixl_state; + + when rti_ixl_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- read ix low + ix_ctrl <= pull_lo_ix; + addr_ctrl <= pull_ad; + dout_ctrl <= ix_lo_dout; + next_state <= rti_pch_state; + + when rti_pch_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- pull pc hi + pc_ctrl <= pull_hi_pc; + addr_ctrl <= pull_ad; + dout_ctrl <= pc_hi_dout; + next_state <= rti_pcl_state; + + when rti_pcl_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle sp + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + sp_ctrl <= latch_sp; + -- pull pc low + pc_ctrl <= pull_lo_pc; + addr_ctrl <= pull_ad; + dout_ctrl <= pc_lo_dout; + next_state <= fetch_state; + + -- + -- here on interrupt + -- iv register hold interrupt type + -- + when int_pcl_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc low + addr_ctrl <= push_ad; + dout_ctrl <= pc_lo_dout; + next_state <= int_pch_state; + + when int_pch_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc hi + addr_ctrl <= push_ad; + dout_ctrl <= pc_hi_dout; + next_state <= int_ixl_state; + + when int_ixl_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write ix low + addr_ctrl <= push_ad; + dout_ctrl <= ix_lo_dout; + next_state <= int_ixh_state; + + when int_ixh_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write ix hi + addr_ctrl <= push_ad; + dout_ctrl <= ix_hi_dout; + next_state <= int_acca_state; + + when int_acca_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write acca + addr_ctrl <= push_ad; + dout_ctrl <= acca_dout; + next_state <= int_accb_state; + + + when int_accb_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write accb + addr_ctrl <= push_ad; + dout_ctrl <= accb_dout; + next_state <= int_cc_state; + + when int_cc_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write cc + addr_ctrl <= push_ad; + dout_ctrl <= cc_dout; + nmi_ctrl <= latch_nmi; + -- + -- nmi is edge triggered + -- nmi_req is cleared when nmi goes low. + -- + if nmi_req = '1' then + iv_ctrl <= nmi_iv; + next_state <= vect_hi_state; + else + -- + -- IRQ is level sensitive + -- + if (irq = '1') and (cc(IBIT) = '0') then + iv_ctrl <= irq_iv; + next_state <= int_mask_state; + else + case op_code is + when "00111110" => -- WAI (wait for interrupt) + iv_ctrl <= latch_iv; + next_state <= int_wai_state; + when "00111111" => -- SWI (Software interrupt) + iv_ctrl <= swi_iv; + next_state <= vect_hi_state; + when others => -- bogus interrupt (return) + iv_ctrl <= latch_iv; + next_state <= rti_state; + end case; + end if; + end if; + + when int_wai_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + op_ctrl <= latch_op; + ea_ctrl <= latch_ea; + -- enable interrupts + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_cli; + cc_ctrl <= load_cc; + sp_ctrl <= latch_sp; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= cc_dout; + if (nmi_req = '1') and (nmi_ack='0') then + iv_ctrl <= nmi_iv; + nmi_ctrl <= set_nmi; + next_state <= vect_hi_state; + else + -- + -- nmi request is not cleared until nmi input goes low + -- + if (nmi_req = '0') and (nmi_ack='1') then + nmi_ctrl <= reset_nmi; + else + nmi_ctrl <= latch_nmi; + end if; + -- + -- IRQ is level sensitive + -- + if (irq = '1') and (cc(IBIT) = '0') then + iv_ctrl <= irq_iv; + next_state <= int_mask_state; + else + iv_ctrl <= latch_iv; + next_state <= int_wai_state; + end if; + end if; + + when int_mask_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- Mask IRQ + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_sei; + cc_ctrl <= load_cc; + sp_ctrl <= latch_sp; + -- idle bus cycle + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= vect_hi_state; + + when halt_state => -- halt CPU. + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- do nothing in ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- idle bus cycle + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + if halt = '1' then + next_state <= halt_state; + else + next_state <= fetch_state; + end if; + + when others => -- error state halt on undefine states + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- do nothing in ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- idle bus cycle + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= error_state; + end case; +end process; + +-------------------------------- +-- +-- state machine +-- +-------------------------------- + +change_state: process( clk, rst, state, hold ) +begin + if clk'event and clk = '0' then + if rst = '1' then + state <= reset_state; + elsif hold = '1' then + state <= state; + else + state <= next_state; + end if; + end if; +end process; + -- output + +end CPU_ARCH; + diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/defender_sound_board.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/defender_sound_board.vhd new file mode 100644 index 00000000..7adbb321 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/defender_sound_board.vhd @@ -0,0 +1,184 @@ +--------------------------------------------------------------------------------- +-- Defender sound board by Dar (darfpga@aol.fr) +-- http://darfpga.blogspot.fr +--------------------------------------------------------------------------------- +-- gen_ram.vhd +-------------------------------- +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com) +-- http://www.syntiac.com/fpga64.html +--------------------------------------------------------------------------------- +-- cpu68 - Version 9th Jan 2004 0.8 +-- 6800/01 compatible CPU core +-- GNU public license - December 2002 : John E. Kent +--------------------------------------------------------------------------------- +-- Educational use only +-- Do not redistribute synthetized file with roms +-- Do not redistribute roms whatever the form +-- Use at your own risk +--------------------------------------------------------------------------------- +-- Version 0.0 -- 15/10/2017 -- +-- initial version +--------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity defender_sound_board is +port( + clk_0p89 : in std_logic; + reset : in std_logic; + hand : out std_logic; + select_sound : in std_logic_vector( 5 downto 0); + audio_out : out std_logic_vector( 7 downto 0); + rom_addr : out std_logic_vector(11 downto 0); + rom_do : in std_logic_vector( 7 downto 0); + rom_vma : out std_logic +); +end defender_sound_board; + +architecture struct of defender_sound_board is + + signal reset_n : std_logic; + + signal cpu_addr : std_logic_vector(15 downto 0); + signal cpu_di : std_logic_vector( 7 downto 0); + signal cpu_do : std_logic_vector( 7 downto 0); + signal cpu_rw : std_logic; + signal cpu_irq : std_logic; + signal cpu_vma : std_logic; + + signal wram_cs : std_logic; + signal wram_we : std_logic; + signal wram_do : std_logic_vector( 7 downto 0); + + signal rom_cs : std_logic; +-- signal rom_do : std_logic_vector( 7 downto 0); + +-- pia port a +-- bit 0-7 audio output + +-- pia port b +-- bit 0-4 select sound input (sel0-4) +-- bit 5-6 switch sound/notes/speech on/off +-- bit 7 sel5 + +-- pia io ca/cb +-- ca1 vdd +-- cb1 sound trigger (sel0-5 = 1) +-- ca2 speech data N/C +-- cb2 speech clock N/C + + signal pia_rw_n : std_logic; + signal pia_cs : std_logic; + signal pia_irqa : std_logic; + signal pia_irqb : std_logic; + signal pia_do : std_logic_vector( 7 downto 0); + signal pia_pa_o : std_logic_vector( 7 downto 0); + signal pia_pb_i : std_logic_vector( 7 downto 0); + signal pia_cb1_i : std_logic; + +begin + +reset_n <= not reset; + +-- pia cs +wram_cs <= '1' when cpu_addr(15 downto 8) = X"00" else '0'; -- 0000-007F +pia_cs <= '1' when cpu_addr(14 downto 12) = "000" and cpu_addr(10) = '1' else '0'; -- 8400-8403 ? => 0400-0403 +rom_cs <= '1' when cpu_addr(15 downto 12) = X"F" else '0'; -- F800-FFFF + +-- write enables +wram_we <= '1' when cpu_rw = '0' and wram_cs = '1' else '0'; +pia_rw_n <= '0' when cpu_rw = '0' and pia_cs = '1' else '1'; + +-- mux cpu in data between roms/io/wram +cpu_di <= + wram_do when wram_cs = '1' else + pia_do when pia_cs = '1' else + rom_do when rom_cs = '1' else X"55"; + +-- pia I/O +audio_out <= pia_pa_o; + +pia_pb_i(5 downto 0) <= select_sound(5 downto 0); +--pia_pb_i(4 downto 0) <= select_sound(4 downto 0); +--pia_pb_i(6 downto 5) <= "11"; -- assume DS1-1 and DS1-2 open +pia_pb_i(6) <= '1'; +pia_pb_i(7) <= '1'; -- Handshake to ? from rom board (drawings are confusing) + +-- pia Cb1 +pia_cb1_i <= '0' when select_sound = "111111" else '1'; + +-- pia irqs to cpu +cpu_irq <= pia_irqa or pia_irqb; + +-- microprocessor 6800 +main_cpu : entity work.cpu68 +port map( + clk => clk_0p89,-- E clock input (falling edge) + rst => reset, -- reset input (active high) + rw => cpu_rw, -- read not write output + vma => cpu_vma, -- valid memory address (active high) + address => cpu_addr, -- address bus output + data_in => cpu_di, -- data bus input + data_out => cpu_do, -- data bus output + hold => '0', -- hold input (active high) extend bus cycle + halt => '0', -- halt input (active high) grants DMA + irq => cpu_irq, -- interrupt request input (active high) + nmi => '0', -- non maskable interrupt request input (active high) + test_alu => open, + test_cc => open +); + +-- cpu program rom +--cpu_prog_rom : entity work.defender_sound +--port map( +-- clk => clk_0p89, +-- addr => cpu_addr(10 downto 0), +-- data => rom_do +--); +rom_vma <= rom_cs and cpu_vma; +rom_addr <= cpu_addr(11 downto 0); + +-- cpu wram +cpu_ram : entity work.gen_ram +generic map( dWidth => 8, aWidth => 7) +port map( + clk => clk_0p89, + we => wram_we, + addr => cpu_addr(6 downto 0), + d => cpu_do, + q => wram_do +); + +-- pia +pia : entity work.pia6821 +port map +( + clk => clk_0p89, + rst => reset, + cs => pia_cs, + rw => pia_rw_n, + addr => cpu_addr(1 downto 0), + data_in => cpu_do, + data_out => pia_do, + irqa => pia_irqa, + irqb => pia_irqb, + pa_i => (others => '0'), + pa_o => pia_pa_o, + pa_oe => open, + ca1 => '1', + ca2_i => '0', + ca2_o => open, + ca2_oe => open, + pb_i => pia_pb_i, + pb_o => open, + pb_oe => open, + cb1 => pia_cb1_i, + cb2_i => '0', + cb2_o => open, + cb2_oe => open +); + +end struct; \ No newline at end of file diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/dpram.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/dpram.vhd new file mode 100644 index 00000000..284194c5 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/dpram.vhd @@ -0,0 +1,81 @@ +-- ----------------------------------------------------------------------- +-- +-- Syntiac's generic VHDL support files. +-- +-- ----------------------------------------------------------------------- +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com) +-- http://www.syntiac.com/fpga64.html +-- +-- Modified April 2016 by Dar (darfpga@aol.fr) +-- http://darfpga.blogspot.fr +-- Remove address register when writing +-- +-- ----------------------------------------------------------------------- +-- +-- dpram.vhd +-- +-- ----------------------------------------------------------------------- +-- +-- generic ram. +-- +-- ----------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.numeric_std.ALL; + +-- ----------------------------------------------------------------------- + +entity dpram is + generic ( + dWidth : integer := 8; + aWidth : integer := 10 + ); + port ( + clk_a : in std_logic; + we_a : in std_logic := '0'; + addr_a : in std_logic_vector((aWidth-1) downto 0); + d_a : in std_logic_vector((dWidth-1) downto 0) := (others => '0'); + q_a : out std_logic_vector((dWidth-1) downto 0); + + clk_b : in std_logic; + we_b : in std_logic := '0'; + addr_b : in std_logic_vector((aWidth-1) downto 0); + d_b : in std_logic_vector((dWidth-1) downto 0) := (others => '0'); + q_b : out std_logic_vector((dWidth-1) downto 0) + ); +end entity; + +-- ----------------------------------------------------------------------- + +architecture rtl of dpram is + subtype addressRange is integer range 0 to ((2**aWidth)-1); + type ramDef is array(addressRange) of std_logic_vector((dWidth-1) downto 0); + signal ram: ramDef; + signal addr_a_reg: std_logic_vector((aWidth-1) downto 0); + signal addr_b_reg: std_logic_vector((aWidth-1) downto 0); +begin + +-- ----------------------------------------------------------------------- + process(clk_a) + begin + if rising_edge(clk_a) then + if we_a = '1' then + ram(to_integer(unsigned(addr_a))) <= d_a; + end if; + q_a <= ram(to_integer(unsigned(addr_a))); + end if; + end process; + + process(clk_b) + begin + if rising_edge(clk_b) then + if we_b = '1' then + ram(to_integer(unsigned(addr_b))) <= d_b; + end if; + q_b <= ram(to_integer(unsigned(addr_b))); + end if; + end process; + +end architecture; + diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/gen_ram.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/gen_ram.vhd new file mode 100644 index 00000000..f1a95608 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/gen_ram.vhd @@ -0,0 +1,84 @@ +-- ----------------------------------------------------------------------- +-- +-- Syntiac's generic VHDL support files. +-- +-- ----------------------------------------------------------------------- +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com) +-- http://www.syntiac.com/fpga64.html +-- +-- Modified April 2016 by Dar (darfpga@aol.fr) +-- http://darfpga.blogspot.fr +-- Remove address register when writing +-- +-- ----------------------------------------------------------------------- +-- +-- gen_rwram.vhd +-- +-- ----------------------------------------------------------------------- +-- +-- generic ram. +-- +-- ----------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.numeric_std.ALL; + +-- ----------------------------------------------------------------------- + +entity gen_ram is + generic ( + dWidth : integer := 8; + aWidth : integer := 10 + ); + port ( + clk : in std_logic; + we : in std_logic; + addr : in std_logic_vector((aWidth-1) downto 0); + d : in std_logic_vector((dWidth-1) downto 0); + q : out std_logic_vector((dWidth-1) downto 0) + ); +end entity; + +-- ----------------------------------------------------------------------- + +architecture rtl of gen_ram is + subtype addressRange is integer range 0 to ((2**aWidth)-1); + type ramDef is array(addressRange) of std_logic_vector((dWidth-1) downto 0); + signal ram: ramDef; + + signal rAddrReg : std_logic_vector((aWidth-1) downto 0); + signal qReg : std_logic_vector((dWidth-1) downto 0); +begin +-- ----------------------------------------------------------------------- +-- Signals to entity interface +-- ----------------------------------------------------------------------- +-- q <= qReg; + +-- ----------------------------------------------------------------------- +-- Memory write +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if we = '1' then + ram(to_integer(unsigned(addr))) <= d; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- Memory read +-- ----------------------------------------------------------------------- +process(clk) + begin + if rising_edge(clk) then +-- qReg <= ram(to_integer(unsigned(rAddrReg))); +-- rAddrReg <= addr; +---- qReg <= ram(to_integer(unsigned(addr))); + q <= ram(to_integer(unsigned(addr))); + end if; + end process; +--q <= ram(to_integer(unsigned(addr))); +end architecture; + diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.qip b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.qip new file mode 100644 index 00000000..d4720390 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "pll_mist.vhd"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_mist.ppf"] diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.vhd new file mode 100644 index 00000000..981d030b --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.vhd @@ -0,0 +1,429 @@ +-- megafunction wizard: %ALTPLL% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altpll + +-- ============================================================ +-- File Name: pll_mist.vhd +-- Megafunction Name(s): +-- altpll +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 Patches 4.26 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY pll_mist IS + PORT + ( + areset : IN STD_LOGIC := '0'; + inclk0 : IN STD_LOGIC := '0'; + c0 : OUT STD_LOGIC ; + c1 : OUT STD_LOGIC ; + c2 : OUT STD_LOGIC ; + locked : OUT STD_LOGIC + ); +END pll_mist; + + +ARCHITECTURE SYN OF pll_mist IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC ; + SIGNAL sub_wire2 : STD_LOGIC ; + SIGNAL sub_wire3 : STD_LOGIC ; + SIGNAL sub_wire4 : STD_LOGIC ; + SIGNAL sub_wire5 : STD_LOGIC ; + SIGNAL sub_wire6 : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL sub_wire7_bv : BIT_VECTOR (0 DOWNTO 0); + SIGNAL sub_wire7 : STD_LOGIC_VECTOR (0 DOWNTO 0); + + + + COMPONENT altpll + GENERIC ( + bandwidth_type : STRING; + clk0_divide_by : NATURAL; + clk0_duty_cycle : NATURAL; + clk0_multiply_by : NATURAL; + clk0_phase_shift : STRING; + clk1_divide_by : NATURAL; + clk1_duty_cycle : NATURAL; + clk1_multiply_by : NATURAL; + clk1_phase_shift : STRING; + clk2_divide_by : NATURAL; + clk2_duty_cycle : NATURAL; + clk2_multiply_by : NATURAL; + clk2_phase_shift : STRING; + compensate_clock : STRING; + inclk0_input_frequency : NATURAL; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + operation_mode : STRING; + pll_type : STRING; + port_activeclock : STRING; + port_areset : STRING; + port_clkbad0 : STRING; + port_clkbad1 : STRING; + port_clkloss : STRING; + port_clkswitch : STRING; + port_configupdate : STRING; + port_fbin : STRING; + port_inclk0 : STRING; + port_inclk1 : STRING; + port_locked : STRING; + port_pfdena : STRING; + port_phasecounterselect : STRING; + port_phasedone : STRING; + port_phasestep : STRING; + port_phaseupdown : STRING; + port_pllena : STRING; + port_scanaclr : STRING; + port_scanclk : STRING; + port_scanclkena : STRING; + port_scandata : STRING; + port_scandataout : STRING; + port_scandone : STRING; + port_scanread : STRING; + port_scanwrite : STRING; + port_clk0 : STRING; + port_clk1 : STRING; + port_clk2 : STRING; + port_clk3 : STRING; + port_clk4 : STRING; + port_clk5 : STRING; + port_clkena0 : STRING; + port_clkena1 : STRING; + port_clkena2 : STRING; + port_clkena3 : STRING; + port_clkena4 : STRING; + port_clkena5 : STRING; + port_extclk0 : STRING; + port_extclk1 : STRING; + port_extclk2 : STRING; + port_extclk3 : STRING; + self_reset_on_loss_lock : STRING; + width_clock : NATURAL + ); + PORT ( + areset : IN STD_LOGIC ; + clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0); + inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0); + locked : OUT STD_LOGIC + ); + END COMPONENT; + +BEGIN + sub_wire7_bv(0 DOWNTO 0) <= "0"; + sub_wire7 <= To_stdlogicvector(sub_wire7_bv); + sub_wire4 <= sub_wire0(2); + sub_wire3 <= sub_wire0(0); + sub_wire1 <= sub_wire0(1); + c1 <= sub_wire1; + locked <= sub_wire2; + c0 <= sub_wire3; + c2 <= sub_wire4; + sub_wire5 <= inclk0; + sub_wire6 <= sub_wire7(0 DOWNTO 0) & sub_wire5; + + altpll_component : altpll + GENERIC MAP ( + bandwidth_type => "AUTO", + clk0_divide_by => 9, + clk0_duty_cycle => 50, + clk0_multiply_by => 32, + clk0_phase_shift => "0", + clk1_divide_by => 9, + clk1_duty_cycle => 50, + clk1_multiply_by => 4, + clk1_phase_shift => "0", + clk2_divide_by => 91, + clk2_duty_cycle => 50, + clk2_multiply_by => 3, + clk2_phase_shift => "0", + compensate_clock => "CLK0", + inclk0_input_frequency => 37037, + intended_device_family => "Cyclone III", + lpm_hint => "CBX_MODULE_PREFIX=pll_mist", + lpm_type => "altpll", + operation_mode => "NORMAL", + pll_type => "AUTO", + port_activeclock => "PORT_UNUSED", + port_areset => "PORT_USED", + port_clkbad0 => "PORT_UNUSED", + port_clkbad1 => "PORT_UNUSED", + port_clkloss => "PORT_UNUSED", + port_clkswitch => "PORT_UNUSED", + port_configupdate => "PORT_UNUSED", + port_fbin => "PORT_UNUSED", + port_inclk0 => "PORT_USED", + port_inclk1 => "PORT_UNUSED", + port_locked => "PORT_USED", + port_pfdena => "PORT_UNUSED", + port_phasecounterselect => "PORT_UNUSED", + port_phasedone => "PORT_UNUSED", + port_phasestep => "PORT_UNUSED", + port_phaseupdown => "PORT_UNUSED", + port_pllena => "PORT_UNUSED", + port_scanaclr => "PORT_UNUSED", + port_scanclk => "PORT_UNUSED", + port_scanclkena => "PORT_UNUSED", + port_scandata => "PORT_UNUSED", + port_scandataout => "PORT_UNUSED", + port_scandone => "PORT_UNUSED", + port_scanread => "PORT_UNUSED", + port_scanwrite => "PORT_UNUSED", + port_clk0 => "PORT_USED", + port_clk1 => "PORT_USED", + port_clk2 => "PORT_USED", + port_clk3 => "PORT_UNUSED", + port_clk4 => "PORT_UNUSED", + port_clk5 => "PORT_UNUSED", + port_clkena0 => "PORT_UNUSED", + port_clkena1 => "PORT_UNUSED", + port_clkena2 => "PORT_UNUSED", + port_clkena3 => "PORT_UNUSED", + port_clkena4 => "PORT_UNUSED", + port_clkena5 => "PORT_UNUSED", + port_extclk0 => "PORT_UNUSED", + port_extclk1 => "PORT_UNUSED", + port_extclk2 => "PORT_UNUSED", + port_extclk3 => "PORT_UNUSED", + self_reset_on_loss_lock => "OFF", + width_clock => 5 + ) + PORT MAP ( + areset => areset, + inclk => sub_wire6, + clk => sub_wire0, + locked => sub_wire2 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "3" +-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "9" +-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "91" +-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +-- Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "96.000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "12.000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "0.890110" +-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps" +-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +-- Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0" +-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "6" +-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "2" +-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "3" +-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "96.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "12.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "0.89000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz" +-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "deg" +-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll_mist.mif" +-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +-- Retrieval info: PRIVATE: SPREAD_USE STRING "0" +-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +-- Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +-- Retrieval info: PRIVATE: STICKY_CLK2 STRING "1" +-- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +-- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: USE_CLK0 STRING "1" +-- Retrieval info: PRIVATE: USE_CLK1 STRING "1" +-- Retrieval info: PRIVATE: USE_CLK2 STRING "1" +-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +-- Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +-- Retrieval info: PRIVATE: USE_CLKENA2 STRING "0" +-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "9" +-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "32" +-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "9" +-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "4" +-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "91" +-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "3" +-- Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +-- Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +-- Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]" +-- Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +-- Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +-- Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2" +-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +-- Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +-- Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +-- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +-- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +-- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +-- Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +-- Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2 +-- Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.ppf TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf +-- Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_4.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_4.vhd new file mode 100644 index 00000000..ab4849dd --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_4.vhd @@ -0,0 +1,54 @@ +library ieee; +use ieee.std_logic_1164.all,ieee.numeric_std.all; + +entity decoder_4 is +port ( + clk : in std_logic; + addr : in std_logic_vector(8 downto 0); + data : out std_logic_vector(7 downto 0) +); +end entity; + +architecture prom of decoder_4 is + type rom is array(0 to 511) of std_logic_vector(7 downto 0); + signal rom_data: rom := ( + X"81",X"02",X"42",X"82",X"03",X"43",X"83",X"04",X"44",X"84",X"05",X"45",X"85",X"06",X"46",X"86", + X"07",X"47",X"87",X"08",X"48",X"88",X"09",X"49",X"89",X"0A",X"4A",X"8A",X"0B",X"4B",X"8B",X"0C", + X"4C",X"8C",X"0D",X"4D",X"8D",X"0E",X"4E",X"8E",X"0F",X"4F",X"8F",X"10",X"50",X"90",X"11",X"51", + X"91",X"12",X"52",X"92",X"13",X"53",X"93",X"14",X"54",X"94",X"15",X"55",X"95",X"16",X"56",X"96", + X"17",X"57",X"97",X"18",X"58",X"98",X"19",X"59",X"99",X"1A",X"5A",X"9A",X"1B",X"5B",X"9B",X"1C", + X"5C",X"9C",X"1D",X"5D",X"9D",X"1E",X"5E",X"9E",X"1F",X"5F",X"9F",X"20",X"60",X"A0",X"21",X"61", + X"A1",X"22",X"62",X"A2",X"23",X"63",X"A3",X"24",X"64",X"A4",X"25",X"65",X"A5",X"26",X"66",X"A6", + X"27",X"67",X"A7",X"28",X"68",X"A8",X"29",X"69",X"A9",X"2A",X"6A",X"AA",X"2B",X"6B",X"AB",X"2C", + X"6C",X"AC",X"2D",X"6D",X"AD",X"2E",X"6E",X"AE",X"2F",X"6F",X"AF",X"30",X"70",X"B0",X"31",X"71", + X"B1",X"32",X"72",X"B2",X"33",X"73",X"B3",X"34",X"74",X"B4",X"35",X"75",X"B5",X"36",X"76",X"B6", + X"37",X"77",X"B7",X"38",X"78",X"B8",X"39",X"79",X"B9",X"3A",X"7A",X"BA",X"3B",X"7B",X"BB",X"3C", + X"7C",X"BC",X"3D",X"7D",X"BD",X"3E",X"7E",X"BE",X"3F",X"7F",X"BF",X"00",X"40",X"80",X"01",X"41", + X"C3",X"CF",X"D0",X"D9",X"D2",X"C9",X"C7",X"C8",X"D4",X"80",X"A8",X"C3",X"A9",X"80",X"B1",X"B9", + X"B8",X"B1",X"80",X"D7",X"C9",X"CC",X"CC",X"C9",X"C1",X"CD",X"D3",X"80",X"C5",X"CC",X"C5",X"C3", + X"D4",X"D2",X"CF",X"CE",X"C9",X"C3",X"D3",X"80",X"C9",X"CE",X"C3",X"AE",X"80",X"C1",X"CC",X"CC", + X"80",X"D2",X"C9",X"C7",X"C8",X"D4",X"D3",X"80",X"D2",X"C5",X"D3",X"C5",X"D2",X"D6",X"C5",X"C4", + X"34",X"B3",X"73",X"33",X"B2",X"72",X"32",X"B1",X"71",X"31",X"B0",X"70",X"30",X"AF",X"6F",X"2F", + X"AE",X"6E",X"2E",X"AD",X"6D",X"2D",X"AC",X"6C",X"2C",X"AB",X"6B",X"2B",X"AA",X"6A",X"2A",X"A9", + X"69",X"29",X"A8",X"68",X"28",X"A7",X"67",X"27",X"A6",X"66",X"26",X"A5",X"65",X"25",X"A4",X"64", + X"24",X"A3",X"63",X"23",X"A2",X"62",X"22",X"A1",X"61",X"21",X"A0",X"60",X"20",X"9F",X"5F",X"1F", + X"9E",X"5E",X"1E",X"9D",X"5D",X"1D",X"9C",X"5C",X"1C",X"9B",X"5B",X"1B",X"9A",X"5A",X"1A",X"99", + X"59",X"19",X"98",X"58",X"18",X"97",X"57",X"17",X"96",X"56",X"16",X"95",X"55",X"15",X"94",X"54", + X"14",X"93",X"53",X"13",X"92",X"52",X"12",X"91",X"51",X"11",X"90",X"50",X"10",X"8F",X"4F",X"0F", + X"8E",X"4E",X"0E",X"8D",X"4D",X"0D",X"8C",X"4C",X"0C",X"8B",X"4B",X"0B",X"8A",X"4A",X"0A",X"89", + X"49",X"09",X"88",X"48",X"08",X"87",X"47",X"07",X"86",X"46",X"06",X"85",X"45",X"05",X"84",X"44", + X"04",X"83",X"43",X"03",X"82",X"42",X"02",X"81",X"74",X"B4",X"35",X"75",X"B5",X"36",X"76",X"B6", + X"37",X"77",X"B7",X"38",X"78",X"B8",X"39",X"79",X"B9",X"3A",X"7A",X"BA",X"3B",X"7B",X"BB",X"3C", + X"7C",X"BC",X"3D",X"7D",X"BD",X"3E",X"7E",X"BE",X"3F",X"7F",X"BF",X"00",X"40",X"80",X"01",X"41", + X"C3",X"CF",X"D0",X"D9",X"D2",X"C9",X"C7",X"C8",X"D4",X"80",X"A8",X"C3",X"A9",X"80",X"B1",X"B9", + X"B8",X"B1",X"80",X"D7",X"C9",X"CC",X"CC",X"C9",X"C1",X"CD",X"D3",X"80",X"C5",X"CC",X"C5",X"C3", + X"D4",X"D2",X"CF",X"CE",X"C9",X"C3",X"D3",X"80",X"C9",X"CE",X"C3",X"AE",X"80",X"C1",X"CC",X"CC", + X"80",X"D2",X"C9",X"C7",X"C8",X"D4",X"D3",X"80",X"D2",X"C5",X"D3",X"C5",X"D2",X"D6",X"C5",X"C4"); +begin +process(clk) +begin + if rising_edge(clk) then + data <= rom_data(to_integer(unsigned(addr))); + end if; +end process; +end architecture; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_6.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_6.vhd new file mode 100644 index 00000000..0e46cdd5 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_6.vhd @@ -0,0 +1,54 @@ +library ieee; +use ieee.std_logic_1164.all,ieee.numeric_std.all; + +entity decoder_6 is +port ( + clk : in std_logic; + addr : in std_logic_vector(8 downto 0); + data : out std_logic_vector(7 downto 0) +); +end entity; + +architecture prom of decoder_6 is + type rom is array(0 to 511) of std_logic_vector(7 downto 0); + signal rom_data: rom := ( + X"00",X"00",X"01",X"02",X"03",X"04",X"05",X"06",X"07",X"08",X"09",X"0A",X"0B",X"0C",X"0D",X"0E", + X"0F",X"10",X"11",X"12",X"13",X"14",X"15",X"16",X"17",X"18",X"19",X"1A",X"1B",X"1C",X"1D",X"1E", + X"1F",X"20",X"21",X"22",X"23",X"24",X"25",X"26",X"27",X"28",X"29",X"2A",X"2B",X"2C",X"2D",X"2E", + X"2F",X"30",X"31",X"32",X"33",X"34",X"35",X"36",X"37",X"38",X"39",X"3A",X"3B",X"3C",X"3D",X"3E", + X"3F",X"40",X"41",X"42",X"43",X"44",X"45",X"46",X"47",X"48",X"49",X"4A",X"4B",X"4C",X"4D",X"4E", + X"4F",X"50",X"51",X"52",X"53",X"54",X"55",X"56",X"57",X"58",X"59",X"5A",X"5B",X"5C",X"5D",X"5E", + X"5F",X"60",X"61",X"62",X"63",X"64",X"65",X"66",X"67",X"68",X"69",X"6A",X"6B",X"6C",X"6D",X"6E", + X"6F",X"70",X"71",X"72",X"73",X"74",X"75",X"76",X"77",X"78",X"79",X"7A",X"7B",X"7C",X"7D",X"7E", + X"7F",X"80",X"81",X"82",X"83",X"84",X"85",X"86",X"87",X"88",X"89",X"8A",X"8B",X"8C",X"8D",X"8E", + X"8F",X"90",X"91",X"92",X"93",X"94",X"95",X"96",X"97",X"98",X"99",X"9A",X"9B",X"9C",X"9D",X"9E", + X"9F",X"A0",X"A1",X"A2",X"A3",X"A4",X"A5",X"A6",X"A7",X"A8",X"A9",X"AA",X"AB",X"AC",X"AD",X"AE", + X"AF",X"B0",X"B1",X"B2",X"B3",X"B4",X"B5",X"B6",X"B7",X"B8",X"B9",X"BA",X"BB",X"BC",X"BD",X"BE", + X"BF",X"C0",X"C1",X"C2",X"C3",X"C4",X"C5",X"C6",X"C7",X"C8",X"C9",X"CA",X"CB",X"CC",X"CD",X"CE", + X"CF",X"D0",X"D1",X"D2",X"D3",X"D4",X"D5",X"D6",X"D7",X"D8",X"D9",X"DA",X"DB",X"DC",X"DD",X"DE", + X"DF",X"E0",X"E1",X"E2",X"E3",X"E4",X"E5",X"E6",X"E7",X"E8",X"E9",X"EA",X"EB",X"EC",X"ED",X"EE", + X"EF",X"F0",X"F1",X"F2",X"F3",X"F4",X"F5",X"F6",X"F7",X"00",X"00",X"00",X"00",X"00",X"00",X"00", + X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"F7",X"F6",X"F5",X"F4",X"F3",X"F2",X"F1",X"F0",X"EF", + X"EE",X"ED",X"EC",X"EB",X"EA",X"E9",X"E8",X"E7",X"E6",X"E5",X"E4",X"E3",X"E2",X"E1",X"E0",X"DF", + X"DE",X"DD",X"DC",X"DB",X"DA",X"D9",X"D8",X"D7",X"D6",X"D5",X"D4",X"D3",X"D2",X"D1",X"D0",X"CF", + X"CE",X"CD",X"CC",X"CB",X"CA",X"C9",X"C8",X"C7",X"C6",X"C5",X"C4",X"C3",X"C2",X"C1",X"C0",X"BF", + X"BE",X"BD",X"BC",X"BB",X"BA",X"B9",X"B8",X"B7",X"B6",X"B5",X"B4",X"B3",X"B2",X"B1",X"B0",X"AF", + X"AE",X"AD",X"AC",X"AB",X"AA",X"A9",X"A8",X"A7",X"A6",X"A5",X"A4",X"A3",X"A2",X"A1",X"A0",X"9F", + X"9E",X"9D",X"9C",X"9B",X"9A",X"99",X"98",X"97",X"96",X"95",X"94",X"93",X"92",X"91",X"90",X"8F", + X"8E",X"8D",X"8C",X"8B",X"8A",X"89",X"88",X"87",X"86",X"85",X"84",X"83",X"82",X"81",X"80",X"7F", + X"7E",X"7D",X"7C",X"7B",X"7A",X"79",X"78",X"77",X"76",X"75",X"74",X"73",X"72",X"71",X"70",X"6F", + X"6E",X"6D",X"6C",X"6B",X"6A",X"69",X"68",X"67",X"66",X"65",X"64",X"63",X"62",X"61",X"60",X"5F", + X"5E",X"5D",X"5C",X"5B",X"5A",X"59",X"58",X"57",X"56",X"55",X"54",X"53",X"52",X"51",X"50",X"4F", + X"4E",X"4D",X"4C",X"4B",X"4A",X"49",X"48",X"47",X"46",X"45",X"44",X"43",X"42",X"41",X"40",X"3F", + X"3E",X"3D",X"3C",X"3B",X"3A",X"39",X"38",X"37",X"36",X"35",X"34",X"33",X"32",X"31",X"30",X"2F", + X"2E",X"2D",X"2C",X"2B",X"2A",X"29",X"28",X"27",X"26",X"25",X"24",X"23",X"22",X"21",X"20",X"1F", + X"1E",X"1D",X"1C",X"1B",X"1A",X"19",X"18",X"17",X"16",X"15",X"14",X"13",X"12",X"11",X"10",X"0F", + X"0E",X"0D",X"0C",X"0B",X"0A",X"09",X"08",X"07",X"06",X"05",X"04",X"03",X"02",X"01",X"00",X"00"); +begin +process(clk) +begin + if rising_edge(clk) then + data <= rom_data(to_integer(unsigned(addr))); + end if; +end process; +end architecture; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu.vhd new file mode 100755 index 00000000..901b252a --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu.vhd @@ -0,0 +1,1096 @@ +----------------------------------------------------------------------- +-- +-- Copyright 2012 ShareBrained Technology, Inc. +-- +-- This file is part of robotron-fpga. +-- +-- robotron-fpga is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- robotron-fpga is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General +-- Public License along with robotron-fpga. If not, see +-- . +-- +-- Jan 2020: +-- Converted from bidirectional data buses to separated buses for SOC usage +-- Changed to orignal 15kHz display timing +-- Replaced PIAs from System09 (the original didn't work in Joust) +-- Added blitter SC2 selection (for Splat) +----------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +--library unisim; +-- use unisim.vcomponents.all; + +entity robotron_cpu is + port( + clock : in std_logic; + blitter_sc2 : in std_logic; + sinistar : in std_logic; + + -- MC6809 signals + A : in std_logic_vector(15 downto 0); + Dout : in std_logic_vector(7 downto 0); + Din : out std_logic_vector(7 downto 0); + RESET_N : out std_logic; + NMI_N : out std_logic; + FIRQ_N : out std_logic; + IRQ_N : out std_logic; + LIC : in std_logic; + AVMA : in std_logic; + R_W_N : in std_logic; + TSC : out std_logic; + HALT_N : out std_logic; + BA : in std_logic; + BS : in std_logic; + BUSY : in std_logic; + E : out std_logic; + Q : out std_logic; + + -- USB + --EppAstb : in std_logic; + --EppDstb : in std_logic; + --UsbFlag : in std_logic; + --EppWait : in std_logic; + --EppDB : in std_logic_vector(7 downto 0); + --UsbClk : in std_logic; + --UsbOE : in std_logic; + --UsbWR : in std_logic; + --UsbPktEnd : in std_logic; + --UsbDir : in std_logic; + --UsbMode : in std_logic; + --UsbAdr : in std_logic_vector(1 downto 0); + + -- Cellular RAM / StrataFlash + MemOE : out std_logic; + MemWR : out std_logic; + + RamAdv : out std_logic; + RamCS : out std_logic; + RamClk : out std_logic; + RamCRE : out std_logic; + RamLB : out std_logic; + RamUB : out std_logic; + RamWait : in std_logic; + + FlashRp : out std_logic; + FlashCS : out std_logic; + FlashStSts : in std_logic; + + MemAdr : out std_logic_vector(23 downto 1); + MemDin : out std_logic_vector(15 downto 0); + MemDout : in std_logic_vector(15 downto 0); + + -- 7-segment display + SEG : out std_logic_vector(6 downto 0); + DP : out std_logic; + AN : out std_logic_vector(3 downto 0); + + -- LEDs + LED : out std_logic_vector(7 downto 0); + + -- Switches + SW : in std_logic_vector(7 downto 0); + + -- Buttons + BTN : in std_logic_vector(3 downto 0); + + -- VGA connector + vgaRed : out std_logic_vector(2 downto 0); + vgaGreen : out std_logic_vector(2 downto 0); + vgaBlue : out std_logic_vector(1 downto 0); + Hsync : out std_logic; + Vsync : out std_logic; + + -- PS/2 connector + --PS2C : in std_logic; + --PS2D : in std_logic; + + -- 12-pin connectors + JA : in std_logic_vector(7 downto 0); + JB : in std_logic_vector(7 downto 0); + SIN_FIRE : in std_logic; + SIN_BOMB : in std_logic; + + -- To sound board + HAND : in std_logic := '1'; + PB : out std_logic_vector(5 downto 0) + ); +end robotron_cpu; + +architecture Behavioral of robotron_cpu is + + signal reset_request : std_logic; + signal reset_counter : unsigned(7 downto 0); + signal reset : std_logic; + + signal clock_12_phase : unsigned(11 downto 0) := (0 => '1', others => '0'); + + signal clock_q_set : boolean; + signal clock_q_clear : boolean; + signal clock_q : std_logic := '0'; + + signal clock_e_set : boolean; + signal clock_e_clear : boolean; + signal clock_e : std_logic := '0'; + + ------------------------------------------------------------------- + + signal video_count : unsigned(14 downto 0) := (others => '0'); + signal video_count_next : unsigned(14 downto 0); + signal video_address_or_mask : unsigned(13 downto 0); + signal video_address : unsigned(13 downto 0) := (others => '0'); + + signal count_240 : std_logic; + signal irq_4ms : std_logic; + + signal horizontal_sync : std_logic; + signal vertical_sync : std_logic; + + signal video_blank : boolean := true; + + ------------------------------------------------------------------- + + signal led_bcd_in : std_logic_vector(15 downto 0); + signal led_bcd_in_digit : std_logic_vector(3 downto 0); + + signal led_counter : unsigned(15 downto 0) := (others => '0'); + signal led_digit_index : unsigned(1 downto 0); + + signal led_segment : std_logic_vector(6 downto 0); + signal led_dp : std_logic; + signal led_anode : std_logic_vector(3 downto 0); + + ------------------------------------------------------------------- + + signal address : std_logic_vector(15 downto 0); + + signal write : boolean; + signal read : boolean; + + ------------------------------------------------------------------- + + signal mpu_address : std_logic_vector(15 downto 0); + signal mpu_data_in : std_logic_vector(7 downto 0); + signal mpu_data_out : std_logic_vector(7 downto 0); + + signal mpu_bus_status : std_logic; + signal mpu_bus_available : std_logic; + + signal mpu_read : boolean; + signal mpu_write : boolean; + + signal mpu_reset : std_logic := '1'; + signal mpu_halt : std_logic := '0'; + signal mpu_halted : boolean := false; + signal mpu_irq : std_logic := '0'; + signal mpu_firq : std_logic := '0'; + signal mpu_nmi : std_logic := '0'; + + ------------------------------------------------------------------- + + signal memory_address : std_logic_vector(15 downto 0); + signal memory_data_in : std_logic_vector(7 downto 0); + signal memory_data_out : std_logic_vector(7 downto 0); + + signal memory_output_enable : boolean := false; + signal memory_write : boolean := false; + signal flash_enable : boolean := false; + + signal ram_enable : boolean := false; + signal ram_lower_enable : boolean := false; + signal ram_upper_enable : boolean := false; + + ------------------------------------------------------------------- + + signal e_rom : std_logic := '0'; + signal screen_control : std_logic := '0'; + + signal rom_access : boolean; + signal ram_access : boolean; + signal hiram_access : boolean; -- Sinistar hiram + signal color_table_access : boolean; + signal widget_pia_access : boolean; + signal rom_pia_access : boolean; + signal blt_register_access : boolean; + signal video_counter_access : boolean; + signal watchdog_access : boolean; + signal control_access : boolean; + signal cmos_access : boolean; + + signal video_counter_value : std_logic_vector(7 downto 0); + + ------------------------------------------------------------------- + + signal SLAM : std_logic := '1'; + signal R_COIN : std_logic := '1'; + signal C_COIN : std_logic := '1'; + signal L_COIN : std_logic := '1'; + signal H_S_RESET : std_logic := '1'; + signal ADVANCE : std_logic := '1'; + signal AUTO_UP : std_logic := '0'; + + signal rom_pia_rs : std_logic_vector(1 downto 0) := (others => '0'); + signal rom_pia_cs : std_logic := '0'; + signal rom_pia_write : std_logic := '0'; + signal rom_pia_data_in : std_logic_vector(7 downto 0); + signal rom_pia_data_out : std_logic_vector(7 downto 0); + signal rom_pia_ca2_out : std_logic; + signal rom_pia_ca2_dir : std_logic; + signal rom_pia_irq_a : std_logic; + signal rom_pia_pa_in : std_logic_vector(7 downto 0); + signal rom_pia_pa_out : std_logic_vector(7 downto 0); + signal rom_pia_pa_dir : std_logic_vector(7 downto 0); + + signal rom_pia_cb2_out : std_logic; + signal rom_pia_cb2_dir : std_logic; + signal rom_pia_irq_b : std_logic; + signal rom_pia_pb_in : std_logic_vector(7 downto 0); + signal rom_pia_pb_out : std_logic_vector(7 downto 0); + signal rom_pia_pb_dir : std_logic_vector(7 downto 0); + + signal rom_led_digit : std_logic_vector(3 downto 0); + + ------------------------------------------------------------------- + + signal MOVE_UP_1 : std_logic := '1'; + signal MOVE_DOWN_1 : std_logic := '1'; + signal MOVE_LEFT_1 : std_logic := '1'; + signal MOVE_RIGHT_1 : std_logic := '1'; + signal PLAYER_1_START : std_logic := '1'; + signal PLAYER_2_START : std_logic := '1'; + signal FIRE_UP_1 : std_logic := '1'; + signal FIRE_DOWN_1 : std_logic := '1'; + signal FIRE_RIGHT_1 : std_logic := '1'; + signal FIRE_LEFT_1 : std_logic := '1'; + signal MOVE_UP_2 : std_logic := '1'; + signal MOVE_DOWN_2 : std_logic := '1'; + signal MOVE_LEFT_2 : std_logic := '1'; + signal MOVE_RIGHT_2 : std_logic := '1'; + signal FIRE_RIGHT_2 : std_logic := '1'; + signal FIRE_UP_2 : std_logic := '1'; + signal FIRE_DOWN_2 : std_logic := '1'; + signal FIRE_LEFT_2 : std_logic := '1'; + + signal board_interface_w1 : std_logic := '1'; -- Upright application: '1' = jumper present + + signal widget_pia_rs : std_logic_vector(1 downto 0) := (others => '0'); + signal widget_pia_cs : std_logic; + signal widget_pia_write : std_logic := '0'; + signal widget_pia_data_in : std_logic_vector(7 downto 0); + signal widget_pia_data_out : std_logic_vector(7 downto 0); + signal widget_pia_ca2_out : std_logic; + signal widget_pia_ca2_dir : std_logic; + signal widget_pia_irq_a : std_logic; + signal widget_pia_pa_in : std_logic_vector(7 downto 0); + signal widget_pia_pa_out : std_logic_vector(7 downto 0); + signal widget_pia_pa_dir : std_logic_vector(7 downto 0); + signal widget_pia_input_select : std_logic; + signal widget_pia_cb2_out : std_logic; + signal widget_pia_cb2_dir : std_logic; + signal widget_pia_irq_b : std_logic; + signal widget_pia_pb_in : std_logic_vector(7 downto 0); + signal widget_pia_pb_out : std_logic_vector(7 downto 0); + signal widget_pia_pb_dir : std_logic_vector(7 downto 0); + + signal widget_ic3_a : std_logic_vector(4 downto 1); + signal widget_ic3_b : std_logic_vector(4 downto 1); + signal widget_ic3_y : std_logic_vector(4 downto 1); + + signal widget_ic4_a : std_logic_vector(4 downto 1); + signal widget_ic4_b : std_logic_vector(4 downto 1); + signal widget_ic4_y : std_logic_vector(4 downto 1); + + ------------------------------------------------------------------- + + signal blt_rs : std_logic_vector(2 downto 0) := (others => '0'); + signal blt_reg_cs : std_logic := '0'; + signal blt_reg_data_in : std_logic_vector(7 downto 0) := (others => '0'); + + signal blt_halt : boolean := false; + signal blt_halt_ack : boolean := false; + signal blt_read : boolean := false; + signal blt_write : boolean := false; + signal blt_blt_ack : std_logic := '0'; + signal blt_address_out : std_logic_vector(15 downto 0); + signal blt_data_in : std_logic_vector(7 downto 0); + signal blt_data_out : std_logic_vector(7 downto 0); + signal blt_en_lower : boolean := false; + signal blt_en_upper : boolean := false; + + ------------------------------------------------------------------- + + function to_std_logic(L: boolean) return std_logic is + begin + if L then + return '1'; + else + return '0'; + end if; + end function; + + subtype pixel_color_t is std_logic_vector(7 downto 0); + type color_table_t is array(0 to 15) of pixel_color_t; + signal color_table : color_table_t; + + signal pixel_nibbles : std_logic_vector(7 downto 0); + signal pixel_byte_l : std_logic_vector(7 downto 0); + signal pixel_byte_h : std_logic_vector(7 downto 0); + + ------------------------------------------------------------------- + + signal decoder_4_in : std_logic_vector(8 downto 0); + signal pseudo_address : std_logic_vector(15 downto 8); + + signal decoder_6_in : std_logic_vector(8 downto 0); + signal video_prom_address : std_logic_vector(13 downto 6); + + ------------------------------------------------------------------- + + signal debug_blt_source_address : std_logic_vector(15 downto 0) := (others => '0'); + signal debug_last_mpu_address : std_logic_vector(15 downto 0) := (others => '0'); + +begin + + -- clock 0 1 2 3 4 5 6 7 8 9 10 11 + -- Q 0 0 0 1 1 1 1 1 1 0 0 0 + -- E 0 0 0 0 0 0 1 1 1 1 1 1 + -- Memory 0 0 1 1 2 2 3 3 4 4 5 5 + + -- Micro 128Mb (8M x 16) CellularRAM MT45W8MW16BGX-701 WT (marking "PW503") + -- MT: Micron Technology + -- 45: PSRAM/CellularRAM memory + -- W: 1.70-1.95V + -- 8M: 8 Meg address space + -- W: 1.7 - 3.6V + -- 16: 16-bit bus + -- B: asynchronous/page/burst read/write operation mode + -- GX: 54-ball "green" VFBGA + -- -70: 70ns access/cycle time + -- 1: 104MHz frequency + -- : standard standby power option + -- WT: -30C to +85C operating temperature + ------------------------------------------------------------------- + -- Asynchronous mode: + -- tRC (read cycle): 70 ns + -- from CE#/OE#/ADDRESS/LB#/UB# asserted to DATA valid and CE#/OE#/ADDRESS/LB#/UB# de-asserted. + -- tWC (write cycle): 70 ns + -- from CE#/ADDRESS/LB#/UB# asserted to DATA valid and CE#/WE#/LB#/UB# de-asserted. + -- tCEM: 4 us maximum + -- from WE# asserted to DATA valid and CE#/WE#/LB#/UB# de-asserted. + + -- Intel JS28F128J3D75 + ------------------------------------------------------------------- + -- Read: + -- 75 ns read/write cycle time + -- 75 ns address to output delay + -- 75 ns CE# to output delay + + reset_request <= BTN(0); + + mpu_reset <= reset; + mpu_halt <= to_std_logic(blt_halt); + mpu_irq <= rom_pia_irq_a or rom_pia_irq_b; + mpu_firq <= '0'; + mpu_nmi <= '0'; + + address <= blt_address_out when mpu_halted else + mpu_address; + write <= blt_write when mpu_halted else + mpu_write; + read <= blt_read when mpu_halted else + mpu_read; + + rom_access <= (address < X"9000" and read and e_rom = '1') or + (address >= X"D000" and read and sinistar='0') or + (address >= X"E000" and read and sinistar='1'); + ram_access <= (address < X"9000" and write) or + (address < X"9000" and read and e_rom = '0') or + (address >= X"9000" and address < X"C000") or + hiram_access; + hiram_access <= + (address >= X"D000" and address < X"E000") and sinistar='1'; + + -- Color table: write: C000-C3FF + color_table_access <= std_match(address, "110000----------"); + + -- Widget PIA: read/write: C8X4 - C8X7 + widget_pia_access <= std_match(address, "11001000----01--"); + + -- ROM PIA: read/write: C8XC - C8XF + rom_pia_access <= std_match(address, "11001000----11--"); + + -- Control address: write: C9XX + control_access <= std_match(address, "11001001--------"); + + -- Special chips: read/write? CAXX + blt_register_access <= std_match(address, "11001010--------"); + + -- Video counter: read: CBXX (even addresses) + video_counter_access <= std_match(address, "11001011-------0"); + + -- Watchdog register: write: CBFE or CBFF + watchdog_access <= std_match(address, "110010111111111-"); + + -- CMOS "nonvolatile" RAM: read/write: CC00 - CFFF + cmos_access <= std_match(address, "110011----------"); + + SLAM <= not SW(6); + H_S_RESET <= not SW(2); + ADVANCE <= not SW(1); + AUTO_UP <= not SW(0); + + PLAYER_1_START <= not BTN(3); + PLAYER_2_START <= not BTN(2); + L_COIN <= not BTN(1); + + MOVE_UP_1 <= JA(0); + MOVE_DOWN_1 <= JA(1); + MOVE_LEFT_1 <= JA(2); + MOVE_RIGHT_1 <= JA(3); + FIRE_UP_1 <= JA(4); + FIRE_DOWN_1 <= JA(5); + FIRE_LEFT_1 <= JA(6); + FIRE_RIGHT_1 <= JA(7); + + MOVE_UP_2 <= JB(0); + MOVE_DOWN_2 <= JB(1); + MOVE_LEFT_2 <= JB(2); + MOVE_RIGHT_2 <= JB(3); + FIRE_UP_2 <= JB(4); + FIRE_DOWN_2 <= JB(5); + FIRE_LEFT_2 <= JB(6); + FIRE_RIGHT_2 <= JB(7); + + video_counter_value <= std_logic_vector(video_address(13 downto 8)) & "00"; + + decoder_4_in <= screen_control & address(15 downto 8); + decoder_6_in <= screen_control & std_logic_vector(video_address(13 downto 6)); + + process(clock) + begin + if rising_edge(clock) then + ram_enable <= false; + ram_lower_enable <= false; + ram_upper_enable <= false; + + flash_enable <= false; + + memory_output_enable <= false; + memory_write <= false; + memory_data_out <= (others => '0'); + + blt_reg_cs <= '0'; + blt_blt_ack <= '0'; + + rom_pia_cs <= '0'; + rom_pia_write <= '0'; + + widget_pia_cs <= '0'; + widget_pia_write <= '0'; + + if clock_12_phase( 0) = '1' then + memory_address <= "00" & video_prom_address & + std_logic_vector(video_address(5 downto 0)); + end if; + + if clock_12_phase( 4) = '1' then + memory_address <= "01" & video_prom_address & + std_logic_vector(video_address(5 downto 0)); + end if; + + if clock_12_phase( 8) = '1' then + memory_address <= "10" & video_prom_address & + std_logic_vector(video_address(5 downto 0)); + end if; + + if clock_12_phase(5) = '1' then + if std_match(video_address(5 downto 0), "11-1--") then + video_blank <= true; + elsif std_match(video_address(5 downto 0), "0---1-") then + video_blank <= false; + end if; + end if; + + if clock_12_phase( 0) = '1' or + clock_12_phase( 4) = '1' or + clock_12_phase( 8) = '1' then + memory_output_enable <= true; + ram_enable <= true; + ram_lower_enable <= true; + ram_upper_enable <= true; + + if video_blank then + vgaRed <= (others => '0'); + vgaGreen <= (others => '0'); + vgaBlue <= (others => '0'); + else + vgaRed <= pixel_byte_h(2 downto 0); + vgaGreen <= pixel_byte_h(5 downto 3); + vgaBlue <= pixel_byte_h(7 downto 6); + end if; + end if; + + if clock_12_phase( 1) = '1' or + clock_12_phase( 5) = '1' or + clock_12_phase( 9) = '1' then + pixel_nibbles <= memory_data_in; + end if; + if clock_12_phase( 2) = '1' or + clock_12_phase( 6) = '1' or + clock_12_phase(10) = '1' then + + pixel_byte_l <= color_table(to_integer(unsigned(pixel_nibbles(3 downto 0)))); + pixel_byte_h <= color_table(to_integer(unsigned(pixel_nibbles(7 downto 4)))); + + if video_blank then + vgaRed <= (others => '0'); + vgaGreen <= (others => '0'); + vgaBlue <= (others => '0'); + else + vgaRed <= pixel_byte_l(2 downto 0); + vgaGreen <= pixel_byte_l(5 downto 3); + vgaBlue <= pixel_byte_l(7 downto 6); + end if; + end if; + + -- BLT-only cycles + -- NOTE: the next cycle must be a read if coming from RAM, since the + -- RAM WE# needs to deassert for a time in order for another write to + -- take place. + if clock_12_phase(11) = '1' or clock_12_phase(1) = '1' then + if mpu_halted then + if ram_access and not hiram_access then + if pseudo_address(15 downto 14) = "11" then + memory_address <= address; + else + memory_address <= pseudo_address(15 downto 14) & + address(7 downto 0) & + pseudo_address(13 downto 8); + end if; + else + memory_address <= address; + end if; + + if ram_access and write then + memory_data_out <= blt_data_out; + memory_write <= true; + else + memory_output_enable <= true; + end if; + + if ram_access then + ram_enable <= true; + ram_lower_enable <= blt_en_lower; + ram_upper_enable <= blt_en_upper; + end if; + + if rom_access then + flash_enable <= true; + end if; + + blt_blt_ack <= '1'; + end if; + end if; + + -- MPU-only cycle + -- NOTE: the next cycle must be a read if coming from RAM, since the + -- RAM WE# needs to deassert for a time in order for another write to + -- take place. + if clock_12_phase(7) = '1' then + if not mpu_halted then + if ram_access and not hiram_access then + if pseudo_address(15 downto 14) = "11" then + memory_address <= address; + else + memory_address <= pseudo_address(15 downto 14) & + address(7 downto 0) & + pseudo_address(13 downto 8); + end if; + else + memory_address <= address; + end if; + + if (ram_access or cmos_access or color_table_access) and write then + memory_data_out <= mpu_data_in; + memory_write <= true; + else + memory_output_enable <= true; + end if; + + if ram_access or cmos_access or color_table_access then + ram_enable <= true; + ram_lower_enable <= true; + ram_upper_enable <= true; + end if; + + if rom_access then + flash_enable <= true; + end if; + + if blt_register_access and write then + blt_rs <= address(2 downto 0); + blt_reg_cs <= '1'; + blt_reg_data_in <= mpu_data_in; + + -- NOTE: To display BLT source address: + if address(2 downto 0) = "010" then + debug_blt_source_address(15 downto 8) <= mpu_data_in; + end if; + + if address(2 downto 0) = "011" then + debug_blt_source_address(7 downto 0) <= mpu_data_in; + end if; + end if; + + if rom_pia_access then + rom_pia_rs <= address(1 downto 0); + rom_pia_data_in <= mpu_data_in; + rom_pia_write <= to_std_logic(write); + rom_pia_cs <= '1'; + end if; + + if widget_pia_access then + widget_pia_rs <= address(1 downto 0); + widget_pia_data_in <= mpu_data_in; + widget_pia_write <= to_std_logic(write); + widget_pia_cs <= '1'; + end if; + + if control_access and write then + screen_control <= mpu_data_in(1); + e_rom <= mpu_data_in(0); + end if; + + if color_table_access and write then + color_table(to_integer(unsigned(address(3 downto 0)))) <= mpu_data_in; + end if; + end if; + end if; + + if clock_12_phase(8) = '1' then + if not mpu_halted then + if read then + if ram_access or rom_access or cmos_access then + mpu_data_out <= memory_data_in; + end if; + + if widget_pia_access then + mpu_data_out <= widget_pia_data_out; + end if; + + if rom_pia_access then + mpu_data_out <= rom_pia_data_out; + end if; + + if video_counter_access then + mpu_data_out <= video_counter_value; + end if; + end if; + end if; + end if; + end if; + end process; + + LED <= mpu_irq & + mpu_halt & + to_std_logic(mpu_halted) & + to_std_logic(ram_access) & + to_std_logic(rom_access) & + to_std_logic(rom_pia_access) & + to_std_logic(widget_pia_access) & + to_std_logic(blt_register_access); + + led_bcd_in <= debug_blt_source_address; + + ------------------------------------------------------------------- + + horizontal_decoder: entity work.decoder_4 + port map( + clk => not clock, + addr => decoder_4_in, + data => pseudo_address + ); + + ------------------------------------------------------------------- + + vertical_decoder: entity work.decoder_6 + port map( + clk => not clock, + addr => decoder_6_in, + data => video_prom_address + ); + + ------------------------------------------------------------------- + + blt_halt_ack <= mpu_halted; + blt_data_in <= memory_data_in; + + blt: entity work.sc1 + port map( + clk => clock, + sc2 => blitter_sc2, + + reg_cs => blt_reg_cs, + reg_data_in => blt_reg_data_in, + rs => blt_rs, + + halt => blt_halt, + halt_ack => blt_halt_ack, + + blt_ack => blt_blt_ack, + blt_address_out => blt_address_out, + + blt_rd => blt_read, + blt_wr => blt_write, + + blt_data_in => blt_data_in, + blt_data_out => blt_data_out, + + en_upper => blt_en_upper, + en_lower => blt_en_lower + ); + + ------------------------------------------------------------------- + + rom_pia_pa_in <= not HAND & + not SLAM & + not C_COIN & + not L_COIN & + not H_S_RESET & + not R_COIN & + not ADVANCE & + not AUTO_UP; + PB(5 downto 0) <= rom_pia_pb_out(5 downto 0); + + rom_led_digit(0) <= rom_pia_pb_out(6); + rom_led_digit(1) <= rom_pia_pb_out(7); + rom_led_digit(2) <= rom_pia_cb2_out; + rom_led_digit(3) <= rom_pia_ca2_out; + rom_pia_pb_in <= (others => '1'); + + rom_pia: entity work.pia6821 + port map( + rst => reset, + clk => clock, + + addr => address(1 downto 0), + cs => rom_pia_cs, + rw => not rom_pia_write, + + data_in => mpu_data_in, + data_out => rom_pia_data_out, + + ca1 => count_240, + ca2_i => '1', + ca2_o => rom_pia_ca2_out, + ca2_oe => rom_pia_ca2_dir, + irqa => rom_pia_irq_a, + pa_i => rom_pia_pa_in, + pa_o => rom_pia_pa_out, + pa_oe => rom_pia_pa_dir, + + cb1 => irq_4ms, + cb2_i => '1', + cb2_o => rom_pia_cb2_out, + cb2_oe => rom_pia_cb2_dir, + irqb => rom_pia_irq_b, + pb_i => rom_pia_pb_in, + pb_o => rom_pia_pb_out, + pb_oe => rom_pia_pb_dir + ); + ------------------------------------------------------------------- + + widget_pia_input_select <= widget_pia_cb2_out; + + widget_ic3_a <= not (MOVE_RIGHT_2 & MOVE_LEFT_2 & MOVE_DOWN_2 & MOVE_UP_2); + widget_ic3_b <= not (MOVE_RIGHT_1 & MOVE_LEFT_1 & MOVE_DOWN_1 & MOVE_UP_1); + + widget_ic3_y <= widget_ic3_b when widget_pia_input_select = '1' else widget_ic3_a; + + widget_ic4_a <= not (FIRE_RIGHT_2 & FIRE_LEFT_2 & FIRE_DOWN_2 & FIRE_UP_2); + widget_ic4_b <= not (FIRE_RIGHT_1 & FIRE_LEFT_1 & FIRE_DOWN_1 & FIRE_UP_1); + + widget_ic4_y <= widget_ic4_b when widget_pia_input_select = '1' else widget_ic4_a; + + widget_pia_pa_in <= widget_ic4_y(2) & + widget_ic4_y(1) & + not PLAYER_2_START & + not PLAYER_1_START & + widget_ic3_y(4) & + widget_ic3_y(3) & + widget_ic3_y(2) & + widget_ic3_y(1) when sinistar = '0' else + widget_ic4_y(4) & + widget_ic4_y(3) & + widget_ic4_y(2) & + widget_ic4_y(1) & + widget_ic3_y(4) & + widget_ic3_y(3) & + widget_ic3_y(2) & + widget_ic3_y(1); + widget_pia_pb_in <= not board_interface_w1 & + "00000" & + widget_ic4_y(4) & + widget_ic4_y(3) when sinistar = '0' else + not board_interface_w1 & + "0" & + not PLAYER_2_START & + not PLAYER_1_START & + "00" & + not SIN_BOMB & + not SIN_FIRE; + + widget_pia: work.pia6821 + port map( + rst => reset, + clk => clock, + + addr => address(1 downto 0), + cs => widget_pia_cs, + rw => not widget_pia_write, + + data_in => mpu_data_in, + data_out => widget_pia_data_out, + + ca1 => '0', + ca2_i => '0', + ca2_o => widget_pia_ca2_out, + ca2_oe => widget_pia_ca2_dir, + irqa => widget_pia_irq_a, + pa_i => widget_pia_pa_in, + pa_o => widget_pia_pa_out, + pa_oe => widget_pia_pa_dir, + + cb1 => '0', + cb2_i => '1', + cb2_o => widget_pia_cb2_out, + cb2_oe => widget_pia_cb2_dir, + irqb => widget_pia_irq_b, + pb_i => widget_pia_pb_in, + pb_o => widget_pia_pb_out, + pb_oe => widget_pia_pb_dir + ); + + ------------------------------------------------------------------- + + E <= clock_e; + Q <= clock_q; + + Din <= mpu_data_out; + + TSC <= '0'; + + process(clock, clock_q_set) + begin + if rising_edge(clock) and clock_q_set then + -- RESET, HALT, interrupts are captured by microprocessor + -- on Q falling edge. Present once per processor clock, + -- on Q rising edge -- just because. + RESET_N <= not mpu_reset; + HALT_N <= not mpu_halt; + IRQ_N <= not mpu_irq; + FIRQ_N <= not mpu_firq; + NMI_N <= not mpu_nmi; + end if; + end process; +-- + process(clock, clock_q_set) + begin + if rising_edge(clock) and clock_q_set then + mpu_address <= A; + mpu_bus_status <= BS; + mpu_bus_available <= BA; + mpu_halted <= BS = '1' and BA = '1'; + mpu_write <= R_W_N = '0' and BA = '0'; + mpu_read <= R_W_N = '1' and BA = '0'; + + if BA = '0' then + debug_last_mpu_address <= A; + end if; + end if; + end process; + + process(clock, clock_e_set) + begin + if rising_edge(clock) and clock_e_set then + mpu_data_in <= Dout; + end if; + end process; + + ------------------------------------------------------------------- + + MemOE <= '0' when memory_output_enable else '1'; + MemWR <= '0' when memory_write else '1'; + + RamAdv <= '0'; + RamCS <= '0' when ram_enable else '1'; + RamClk <= '0'; + RamCRE <= '0'; + RamLB <= '0' when ram_lower_enable else '1'; + RamUB <= '0' when ram_upper_enable else '1'; + + FlashRp <= '1'; + FlashCS <= '0' when flash_enable else '1'; + + MemAdr <= "0000000" & memory_address; + + MemDin <= memory_data_out(7 downto 4) & + memory_data_out(7 downto 4) & + memory_data_out(3 downto 0) & + memory_data_out(3 downto 0); + memory_data_in <= MemDout(11 downto 8) & MemDout(3 downto 0); + + ------------------------------------------------------------------- + -- Video output + + Hsync <= not horizontal_sync; + Vsync <= not vertical_sync; + + ------------------------------------------------------------------- + + DP <= led_dp; + SEG <= led_segment; + AN <= led_anode; + + ------------------------------------------------------------------- + -- 1MHz, 12-phase counter. + + process(clock) + begin + if rising_edge(clock) then + clock_12_phase <= clock_12_phase rol 1; + end if; + end process; + + ------------------------------------------------------------------- + -- Q clock + + clock_q_set <= clock_12_phase(2) = '1'; + clock_q_clear <= clock_12_phase(8) = '1'; + + process(clock) + begin + if rising_edge(clock) then + if clock_q_set then + clock_q <= '1'; + elsif clock_q_clear then + clock_q <= '0'; + end if; + end if; + end process; + + ------------------------------------------------------------------- + -- E clock + + clock_e_set <= clock_12_phase(5) = '1'; + clock_e_clear <= clock_12_phase(11) = '1'; + + process(clock) + begin + if rising_edge(clock) then + if clock_e_set then + clock_e <= '1'; + elsif clock_e_clear then + clock_e <= '0'; + end if; + end if; + end process; + + ------------------------------------------------------------------- + -- Reset generator + + process(clock) + begin + if rising_edge(clock) then + if reset_request = '1' then + reset_counter <= (others => '0'); + reset <= '1'; + else + if reset_counter < 100 then + reset_counter <= reset_counter + 1; + else + reset <= '0'; + end if; + end if; + end if; + end process; + + ------------------------------------------------------------------- + -- Video counter + + video_count_next <= video_count + 1 when (video_count /= 16639) + else (others => '0'); + video_address_or_mask <= "11111100000000" when video_count_next(14) = '1' else (others => '0'); +-- irq_4ms <= video_count(11); + irq_4ms <= video_address(11); + + process(clock, clock_e_clear) + begin + -- Advance video count at end of video memory phase. + if rising_edge(clock) and clock_e_clear then + --watchdog_increment <= '0'; + video_count <= video_count_next; + video_address <= video_count_next(13 downto 0) or video_address_or_mask; + --video_address <= video_address + 1; + --if video_count(14 downto 0) = "011111111111111" then + -- watchdog_increment <= '1'; + --end if; + end if; + end process; + + ------------------------------------------------------------------- + -- Video generator + + count_240 <= '1' when video_address(13 downto 10) = "1111" else '0'; + + horizontal_sync <= '1' when video_address(5 downto 2) = "1110" else '0'; + vertical_sync <= '1' when video_address(13 downto 9) = "11111" else '0'; + + ------------------------------------------------------------------- + -- LED numeric display + + process(clock) + begin + if rising_edge(clock) then + led_counter <= led_counter + 1; + end if; + end process; + + led_digit_index <= led_counter(15 downto 14); + + with led_digit_index select + led_anode <= "1110" when "00", + "1101" when "01", + "1011" when "10", + "0111" when "11", + "1111" when others; + + with led_digit_index select + led_bcd_in_digit <= led_bcd_in( 3 downto 0) when "00", + led_bcd_in( 7 downto 4) when "01", + led_bcd_in(11 downto 8) when "10", + led_bcd_in(15 downto 12) when "11", + "XXXX" when others; + +-- bcd_demux: led_decoder +-- port map( +-- input => led_bcd_in_digit, +-- output => led_segment +-- ); + + led_dp <= '1'; + +end Behavioral; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu_test.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu_test.vhd new file mode 100755 index 00000000..cd1cabaf --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu_test.vhd @@ -0,0 +1,363 @@ +----------------------------------------------------------------------- +-- +-- Copyright 2012 ShareBrained Technology, Inc. +-- +-- This file is part of robotron-fpga. +-- +-- robotron-fpga is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- robotron-fpga is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General +-- Public License along with robotron-fpga. If not, see +-- . +-- +----------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +entity robotron_cpu_test is +end robotron_cpu_test; + +architecture behavior of robotron_cpu_test is + + component robotron_cpu + port( + CLK : in std_logic; + + -- MC6809E interface + A : in std_logic_vector(15 downto 0); + D : inout std_logic_vector(7 downto 0); + RESET_N : out std_logic; + NMI_N : out std_logic; + FIRQ_N : out std_logic; + IRQ_N : out std_logic; + LIC : in std_logic; + AVMA : in std_logic; + R_W_N : in std_logic; + TSC : out std_logic; + HALT_N : out std_logic; + BA : in std_logic; + BS : in std_logic; + BUSY : in std_logic; + E : out std_logic; + Q : out std_logic; + + -- RAM and flash memories + MemOE : out std_logic; + MemWR : out std_logic; + + RamAdv : out std_logic; + RamCS : out std_logic; + RamClk : out std_logic; + RamCRE : out std_logic; + RamLB : out std_logic; + RamUB : out std_logic; + RamWait : in std_logic; + + FlashRp : out std_logic; + FlashCS : out std_logic; + FlashStSts : in std_logic; + + MemAdr : out std_logic_vector(23 downto 1); + MemDB : inout std_logic_vector(15 downto 0); + + -- 7-segment display + SEG : out std_logic_vector(6 downto 0); + DP : out std_logic; + AN : out std_logic_vector(3 downto 0); + + -- LEDs + LED : out std_logic_vector(7 downto 0); + + -- Switches + SW : in std_logic_vector(7 downto 0); + + -- Buttons + BTN : in std_logic_vector(3 downto 0); + + -- VGA + vgaRed : out std_logic_vector(2 downto 0); + vgaGreen : out std_logic_vector(2 downto 0); + vgaBlue : out std_logic_vector(1 downto 0); + Hsync : out std_logic; + Vsync : out std_logic + ); + end component; + + constant CLK_frequency : real := 48.0e6; + constant CLK_period : time := 1 sec / CLK_frequency; + + signal CLK : std_logic := '0'; + + signal A : std_logic_vector(15 downto 0) := (others => '0'); + signal D : std_logic_vector(7 downto 0); + signal RESET_N : std_logic := '1'; + signal NMI_N : std_logic := '1'; + signal FIRQ_N : std_logic := '1'; + signal IRQ_N : std_logic := '1'; + signal LIC : std_logic := '0'; + signal AVMA : std_logic := '0'; + signal R_W_N : std_logic := '0'; + signal TSC : std_logic := '0'; + signal HALT_N : std_logic := '1'; + signal BA : std_logic := '0'; + signal BS : std_logic := '0'; + signal BUSY : std_logic := '0'; + signal E : std_logic := '0'; + signal Q : std_logic := '0'; + + signal MemOE : std_logic; + signal MemWR : std_logic; + + signal RamAdv : std_logic; + signal RamCS : std_logic; + signal RamClk : std_logic; + signal RamCRE : std_logic; + signal RamLB : std_logic; + signal RamUB : std_logic; + signal RamWait : std_logic; + + signal FlashRp : std_logic; + signal FlashCS : std_logic; + signal FlashStSts : std_logic; + + signal MemAdr : std_logic_vector(23 downto 1); + signal MemDB : std_logic_vector(15 downto 0); + + signal SEG : std_logic_vector(6 downto 0); + signal DP : std_logic; + signal AN : std_logic_vector(3 downto 0); + + signal LED : std_logic_vector(7 downto 0); + + signal SW : std_logic_vector(7 downto 0) := (others => '0'); + + signal BTN : std_logic_vector(3 downto 0) := (others => '0'); + + signal vgaRed : std_logic_vector(2 downto 0); + signal vgaGreen : std_logic_vector(2 downto 0); + signal vgaBlue : std_logic_vector(1 downto 0); + signal Hsync : std_logic; + signal Vsync : std_logic; + + ------------------------------------------------------------------- + + signal bus_address : std_logic_vector(15 downto 0) := (others => '1'); + signal bus_read : std_logic := '1'; + signal bus_data : std_logic_vector(7 downto 0) := (others => 'Z'); + signal bus_available: std_logic := 'Z'; + signal bus_status : std_logic := 'Z'; + +begin + + uut: robotron_cpu PORT MAP ( + CLK => CLK, + A => A, + D => D, + RESET_N => RESET_N, + NMI_N => NMI_N, + FIRQ_N => FIRQ_N, + IRQ_N => IRQ_N, + LIC => LIC, + AVMA => AVMA, + R_W_N => R_W_N, + TSC => TSC, + HALT_N => HALT_N, + BA => BA, + BS => BS, + BUSY => BUSY, + E => E, + Q => Q, + MemOE => MemOE, + MemWR => MemWR, + RamAdv => RamAdv, + RamCS => RamCS, + RamClk => RamClk, + RamCRE => RamCRE, + RamLB => RamLB, + RamUB => RamUB, + RamWait => RamWait, + FlashRp => FlashRp, + FlashCS => FlashCS, + FlashStSts => FlashStSts, + MemAdr => MemAdr, + MemDB => MemDB, + SEG => SEG, + DP => DP, + AN => AN, + LED => LED, + SW => SW, + BTN => BTN, + vgaRed => vgaRed, + vgaGreen => vgaGreen, + vgaBlue => vgaBlue, + Hsync => Hsync, + Vsync => Vsync + ); + + CLK_process :process + begin + CLK <= '0'; + wait for CLK_period/2; + CLK <= '1'; + wait for CLK_period/2; + end process; + + bus_process: process + begin + wait until falling_edge(E); + + -- E=0 + 0 ns + wait for 20 ns; + R_W_N <= 'U'; + A <= (others => 'U'); + BA <= 'U'; + BS <= 'U'; + + -- E=0 + 20 ns + wait for 10 ns; + D <= (others => 'Z'); + + -- E=0 + 30 ns + wait for 170 ns; + + if bus_available = '0' then + R_W_N <= bus_read; + A <= bus_address; + else + R_W_N <= 'Z'; + A <= (others => 'Z'); + end if; + + BA <= bus_available; + BS <= bus_status; + + -- E=0 + 200 ns + wait until rising_edge(Q); + + -- Q=1 + wait for 200 ns; + + -- Q=1 + 200 ns + if bus_available = '0' then + if bus_read = '0' then + D <= bus_data; + end if; + end if; + end process; + + stim_proc: process + begin + BTN(0) <= '1'; + wait for 100 ns; + BTN(0) <= '0'; + + wait until rising_edge(RESET_N); + + wait until falling_edge(E); + bus_available <= '0'; + bus_status <= '0'; + + bus_address <= X"FFFE"; + bus_read <= '1'; + bus_data <= (others => 'Z'); + + wait until falling_edge(E); + bus_address <= X"9000"; + bus_read <= '1'; + bus_data <= (others => 'Z'); + + wait until falling_edge(E); + bus_address <= X"0000"; + bus_read <= '0'; + bus_data <= X"69"; + + -- Turn on ROM PIA CA2 + wait until falling_edge(E); + bus_address <= X"C80D"; + bus_read <= '0'; + bus_data <= X"3C"; + + -- IDLE + wait until falling_edge(E); + bus_address <= (others => 'Z'); + bus_read <= '1'; + bus_data <= (others => 'Z'); + + -- Turn off ROM PIA CA2 + wait until falling_edge(E); + bus_address <= X"C80D"; + bus_read <= '0'; + bus_data <= X"34"; + + -- Write BLT + wait until falling_edge(E); + bus_address <= X"CA02"; + bus_read <= '0'; + bus_data <= X"D0"; + + wait until falling_edge(E); + bus_address <= X"CA03"; + bus_read <= '0'; + bus_data <= X"00"; + + wait until falling_edge(E); + bus_address <= X"CA04"; + bus_read <= '0'; + bus_data <= X"33"; + + wait until falling_edge(E); + bus_address <= X"CA05"; + bus_read <= '0'; + bus_data <= X"44"; + + wait until falling_edge(E); + bus_address <= X"CA06"; + bus_read <= '0'; + bus_data <= X"00"; + + wait until falling_edge(E); + bus_address <= X"CA07"; + bus_read <= '0'; + bus_data <= X"00"; + + wait until falling_edge(E); + bus_address <= X"CA00"; + bus_read <= '0'; + bus_data <= X"01"; + + -- IDLE + wait until falling_edge(E); + bus_address <= (others => 'Z'); + bus_read <= '1'; + bus_data <= (others => 'Z'); + + -- HALT should assert from BLT. + wait until falling_edge(E); + wait until falling_edge(E); + + wait until falling_edge(E); + -- Release bus to BLT. + bus_status <= '1'; + bus_available <= '1'; + + -- HALT should deassert from BLT. + wait until falling_edge(E); + wait until falling_edge(E); + wait until falling_edge(E); + + wait; + end process; + +end; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1.vhd new file mode 100644 index 00000000..e3269afb --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1.vhd @@ -0,0 +1,240 @@ +----------------------------------------------------------------------- +-- +-- Copyright 2012 ShareBrained Technology, Inc. +-- +-- This file is part of robotron-fpga. +-- +-- robotron-fpga is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- robotron-fpga is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General +-- Public License along with robotron-fpga. If not, see +-- . +-- +----------------------------------------------------------------------- + +-- This entity models a pair of Williams SC1 pixel BLTter ICs. +-- The interface is modified to be more conducive to synchronous +-- FPGA implementation. +-- Dec 2018 changes for SC1 or SC2 and 0 address error (DW oldgit) + +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_unsigned.all; + +entity sc1 is +port( + clk : in std_logic; + sc2 : in std_logic; + + reg_cs : in std_logic; + reg_data_in : in std_logic_vector( 7 downto 0); + rs : in std_logic_vector( 2 downto 0); + + halt : out boolean; + halt_ack : in boolean; + + blt_ack : in std_logic; + + blt_rd : out boolean; + blt_wr : out boolean; + + blt_address_out : out std_logic_vector(15 downto 0); + blt_data_in : in std_logic_vector( 7 downto 0); + blt_data_out : out std_logic_vector( 7 downto 0); + + en_upper : out boolean; + en_lower : out boolean +); +end sc1; + +architecture RTL of sc1 is + + type state_t is (state_idle, state_wait_for_halt, state_src, state_dst); + + -- control attributes + signal ctrl_span_src : std_logic := '0'; + signal ctrl_span_dst : std_logic := '0'; + signal ctrl_slow : std_logic := '0'; + signal ctrl_foreground : std_logic := '0'; + signal ctrl_solid : std_logic := '0'; + signal ctrl_shift : std_logic := '0'; + signal ctrl_no_lower : std_logic := '0'; + signal ctrl_no_upper : std_logic := '0'; + + -- 0: Run register + signal reg_ctrl : std_logic_vector( 7 downto 0) := (others => '0'); + -- 1: solid value + signal reg_solid : std_logic_vector( 7 downto 0) := (others => '0'); + -- 2, 3: source address + signal reg_src_base : std_logic_vector(15 downto 0) := (others => '0'); + -- 4, 5: destination address + signal reg_dst_base : std_logic_vector(15 downto 0) := (others => '0'); + -- 6: width + signal reg_width : std_logic_vector( 7 downto 0) := (others => '0'); + -- 7: height + signal reg_height : std_logic_vector( 7 downto 0) := (others => '0'); + + -- Internal + signal state : state_t := state_idle; + + signal blt_src_data : std_logic_vector( 7 downto 0) := (others => '0'); + signal blt_shift : std_logic_vector( 3 downto 0) := (others => '0'); + + signal src_address : std_logic_vector(15 downto 0) := (others => '0'); + signal dst_address : std_logic_vector(15 downto 0) := (others => '0'); + + signal x_count : std_logic_vector( 7 downto 0) := (others => '0'); + signal x_count_next : std_logic_vector( 7 downto 0) := (others => '0'); + signal y_count : std_logic_vector( 7 downto 0) := (others => '0'); + signal y_count_next : std_logic_vector( 7 downto 0) := (others => '0'); + + signal xorval : std_logic_vector( 7 downto 0) := (others => '0'); + +begin + -- SC1 had a bug so values had to be xored with 0X04, SC2 fixed the bug so no xor required + xorval <= x"04" when sc2='0' else x"00"; + + halt <= not (state = state_idle); + blt_rd <= (state = state_src); + blt_wr <= (state = state_dst); + + blt_address_out <= dst_address when (state = state_dst) else src_address; + + en_upper <= (state = state_src) or (not (ctrl_no_upper = '1' or (ctrl_foreground = '1' and blt_src_data(7 downto 4) = x"0") )); + en_lower <= (state = state_src) or (not (ctrl_no_lower = '1' or (ctrl_foreground = '1' and blt_src_data(3 downto 0) = x"0") )); + + blt_data_out <= reg_solid when ctrl_solid = '1' else blt_src_data; + + x_count_next <= x_count + 1; + y_count_next <= y_count + 1; + + -- break out control reg into individual signals + ctrl_no_upper <= reg_ctrl(7); + ctrl_no_lower <= reg_ctrl(6); + ctrl_shift <= reg_ctrl(5); + ctrl_solid <= reg_ctrl(4); + ctrl_foreground <= reg_ctrl(3); + --ctrl_slow <= reg_ctrl(2); + ctrl_span_dst <= reg_ctrl(1); + ctrl_span_src <= reg_ctrl(0); + + -- register access + process(clk) + begin + if rising_edge(clk) then + if reg_cs = '1' then + case rs is + -- 0: Start BLT with control attributes + when "000" => reg_ctrl <= reg_data_in; + -- 1: mask + when "001" => reg_solid <= reg_data_in; + -- 2: source address high + when "010" => reg_src_base(15 downto 8) <= reg_data_in; + -- 3: source address low + when "011" => reg_src_base( 7 downto 0) <= reg_data_in; + -- 4: destination address high + when "100" => reg_dst_base(15 downto 8) <= reg_data_in; + -- 5: destination address low + when "101" => reg_dst_base( 7 downto 0) <= reg_data_in; + -- 6: width + when "110" => reg_width <= reg_data_in xor xorval; + -- 7: height + when "111" => reg_height <= reg_data_in xor xorval; + -- Do nothing. + when others => null; + end case; + end if; + end if; + end process; + + -- state machine + process(clk) + begin + if rising_edge(clk) then + case state is + when state_idle => + if reg_cs = '1' and rs = "000" then + state <= state_wait_for_halt; + end if; + + when state_wait_for_halt => + if halt_ack then + src_address <= reg_src_base; + dst_address <= reg_dst_base; + + x_count <= (others => '0'); + y_count <= (others => '0'); + blt_shift <= (others => '0'); + + state <= state_src; + end if; + + when state_src => + if blt_ack = '1' then + if ctrl_shift = '0' then + -- unshifted + blt_src_data <= blt_data_in; + else + -- shifted right one pixel + blt_shift <= blt_data_in( 3 downto 0); + blt_src_data <= blt_shift & blt_data_in( 7 downto 4); + end if; + state <= state_dst; + end if; + + when state_dst => + if blt_ack = '1' then + state <= state_src; + + if x_count_next < reg_width then + x_count <= x_count_next; + + if ctrl_span_src = '1' then + src_address <= src_address + 256; + else + src_address <= src_address + 1; + end if; + + if ctrl_span_dst = '1' then + dst_address <= dst_address + 256; + else + dst_address <= dst_address + 1; + end if; + else + x_count <= (others => '0'); + y_count <= y_count_next; + + if y_count_next = reg_height then + state <= state_idle; + end if; + + if ctrl_span_src = '1' then + src_address <= reg_src_base + y_count_next; + else + src_address <= src_address + 1; + end if; + + if ctrl_span_dst = '1' then + dst_address <= reg_dst_base + y_count_next; + else + dst_address <= dst_address + 1; + end if; + + end if; + end if; + -- Do nothing. + when others => null; + end case; + end if; + end process; +end RTL; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1_tb.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1_tb.vhd new file mode 100755 index 00000000..6433d45b --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1_tb.vhd @@ -0,0 +1,160 @@ +----------------------------------------------------------------------- +-- +-- Copyright 2012 ShareBrained Technology, Inc. +-- +-- This file is part of robotron-fpga. +-- +-- robotron-fpga is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- robotron-fpga is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General +-- Public License along with robotron-fpga. If not, see +-- . +-- +----------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +entity sc1_tb is +end sc1_tb; + +architecture behavior of sc1_tb is + + component sc1 + port( + clk : in std_logic; + reset : in std_logic; + e_sync : in std_logic; + reg_cs : in std_logic; + reg_data_in : in std_logic_vector(7 downto 0); + rs : in std_logic_vector(2 downto 0); + halt : out boolean; + halt_ack : in boolean; + blt_ack : in std_logic; + blt_address_out : out std_logic_vector(15 downto 0); + read : out boolean; + write : out boolean; + blt_data_in : in std_logic_vector(7 downto 0); + blt_data_out : out std_logic_vector(7 downto 0); + en_upper : out boolean; + en_lower : out boolean + ); + end component; + + signal clk : std_logic := '0'; + signal reset : std_logic := '0'; + signal e_sync : std_logic := '0'; + signal reg_cs : std_logic := '0'; + signal reg_data_in : std_logic_vector(7 downto 0) := (others => '0'); + signal rs : std_logic_vector(2 downto 0) := (others => '0'); + signal halt : boolean := false; + signal halt_ack : boolean := false; + signal blt_ack : std_logic := '0'; + signal blt_address_out : std_logic_vector(15 downto 0); + signal read : boolean := false; + signal write : boolean := false; + signal blt_data_in : std_logic_vector(7 downto 0) := (others => '0'); + signal blt_data_out : std_logic_vector(7 downto 0); + signal en_upper : boolean; + signal en_lower : boolean; + + constant clk_period : time := 83.333333 ns; + +begin + + uut: sc1 + port map( + clk => clk, + reset => reset, + e_sync => e_sync, + reg_cs => reg_cs, + reg_data_in => reg_data_in, + rs => rs, + halt => halt, + halt_ack => halt_ack, + blt_ack => blt_ack, + blt_address_out => blt_address_out, + read => read, + write => write, + blt_data_in => blt_data_in, + blt_data_out => blt_data_out, + en_upper => en_upper, + en_lower => en_lower + ); + + clk_process: process + begin + clk <= '0'; + wait for clk_period/2; + + clk <= '1'; + wait for clk_period/2; + end process; + + stim_proc: process + begin + e_sync <= '1'; + + wait until rising_edge(clk); + rs <= "010"; + reg_data_in <= X"11"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "011"; + reg_data_in <= X"22"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "100"; + reg_data_in <= X"33"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "101"; + reg_data_in <= X"44"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "110"; + reg_data_in <= X"00"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "111"; + reg_data_in <= X"00"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "000"; + reg_data_in <= "00000001"; + reg_cs <= '1'; + + wait until rising_edge(clk); + reg_cs <= '0'; + + wait until halt = true; + halt_ack <= true; + + wait until rising_edge(clk); + blt_ack <= '1'; + blt_data_in <= X"69"; + + wait until halt = false; + blt_ack <= '0'; + halt_ack <= false; + + wait; + end process; + +end; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_soc.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_soc.vhd new file mode 100644 index 00000000..99769a4f --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_soc.vhd @@ -0,0 +1,262 @@ +----------------------------------------------------------------------- +-- +-- A SOC-like top-level for robotron-fpga +-- (C) 2020 Slingshot +-- +-- MC6809 Cycle-Accurate 6809 Core +-- (c) 2016, Greg Miller +-- +-- Defender sound board by Dar (darfpga@aol.fr) +-- +-- robotron-fpga is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- robotron-fpga is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General +-- Public License along with robotron-fpga. If not, see +-- . +-- +----------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +entity robotron_soc is +port ( + clock : in std_logic; -- 12MHz + clock_snd : in std_logic; -- 0.89MHz + + -- Cellular RAM / StrataFlash + MemOE : out std_logic; + MemWR : out std_logic; + + RamAdv : out std_logic; + RamCS : out std_logic; + RamClk : out std_logic; + RamCRE : out std_logic; + RamLB : out std_logic; + RamUB : out std_logic; + RamWait : in std_logic; + + FlashRp : out std_logic; + FlashCS : out std_logic; + FlashStSts : in std_logic; + + MemAdr : out std_logic_vector(23 downto 1); + MemDin : out std_logic_vector(15 downto 0); + MemDout : in std_logic_vector(15 downto 0); + + blitter_sc2 : in std_logic; + sinistar : in std_logic; + + -- Switches + SW : in std_logic_vector(7 downto 0); + + -- Buttons + BTN : in std_logic_vector(3 downto 0); + SIN_FIRE : in std_logic; + SIN_BOMB : in std_logic; + + -- VGA connector + vgaRed : out std_logic_vector(2 downto 0); + vgaGreen : out std_logic_vector(2 downto 0); + vgaBlue : out std_logic_vector(1 downto 0); + Hsync : out std_logic; + Vsync : out std_logic; + + -- Audio + audio_out : out std_logic_vector(7 downto 0); + + -- 12-pin connectors + JA : in std_logic_vector(7 downto 0); + JB : in std_logic_vector(7 downto 0); + + dl_clock : in std_logic; + dl_addr : in std_logic_vector(15 downto 0); + dl_data : in std_logic_vector(7 downto 0); + dl_wr : in std_logic +); +end robotron_soc; + +architecture Behavioral of robotron_soc is + +component mc6809i is +port ( + D : in std_logic_vector( 7 downto 0); + Dout : out std_logic_vector( 7 downto 0); + ADDR : out std_logic_vector(15 downto 0); + RnW : out std_logic; + E : in std_logic; + Q : in std_logic; + BS : out std_logic; + BA : out std_logic; + nIRQ : in std_logic := '1'; + nFIRQ : in std_logic := '1'; + nNMI : in std_logic := '1'; + AVMA : out std_logic; + BUSY : out std_logic; + LIC : out std_logic; + nHALT : in std_logic := '1'; + nRESET : in std_logic := '1'; + nDMABREQ : in std_logic := '1' +); +end component mc6809i; + +signal cpu_a : std_logic_vector(15 downto 0); +signal cpu_dout : std_logic_vector( 7 downto 0); +signal cpu_din : std_logic_vector( 7 downto 0); +signal cpu_reset_n : std_logic; +signal cpu_nmi_n : std_logic; +signal cpu_firq_n : std_logic; +signal cpu_irq_n : std_logic; +signal cpu_lic : std_logic; +signal cpu_avma : std_logic; +signal cpu_rwn : std_logic; +signal cpu_halt_n : std_logic; +signal cpu_ba : std_logic; +signal cpu_bs : std_logic; +signal cpu_busy : std_logic; +signal cpu_e : std_logic; +signal cpu_q : std_logic; + +signal hand : std_logic; +signal select_sound : std_logic_vector( 5 downto 0); + +signal snd_addr : std_logic_vector(11 downto 0); +signal snd_do : std_logic_vector( 7 downto 0); +signal snd_rom_we : std_logic; + +begin + +mc6809: mc6809i +port map ( + ADDR => cpu_a, + Dout => cpu_dout, + D => cpu_din, + nReset => cpu_reset_n, + nNMI => cpu_nmi_n, + nFIRQ => cpu_firq_n, + nIRQ => cpu_irq_n, + LIC => cpu_lic, + AVMA => cpu_avma, + RnW => cpu_rwn, + nHALT => cpu_halt_n, + BA => cpu_ba, + BS => cpu_bs, + BUSY => cpu_busy, + E => cpu_e, + Q => cpu_q +); + +cpu_board: entity work.robotron_cpu +port map ( + clock => clock, + blitter_sc2 => blitter_sc2, + sinistar => sinistar, + + A => cpu_a, + Dout => cpu_dout, + Din => cpu_din, + RESET_N => cpu_reset_n, + NMI_N => cpu_nmi_n, + FIRQ_N => cpu_firq_n, + IRQ_N => cpu_irq_n, + LIC => cpu_lic, + AVMA => cpu_avma, + R_W_N => cpu_rwn, + TSC => open, + HALT_N => cpu_halt_n, + BA => cpu_ba, + BS => cpu_bs, + BUSY => cpu_busy, + E => cpu_e, + Q => cpu_q, + + -- Cellular RAM / StrataFlash + MemOE => MemOE, + MemWR => MemWR, + + RamAdv => RamAdv, + RamCS => RamCS, + RamClk => RamClk, + RamCRE => RamCRE, + RamLB => RamLB, + RamUB => RamUB, + RamWait => RamWait, + + FlashRp => FlashRp, + FlashCS => FlashCS, + FlashStSts => FlashStSts, + + MemAdr => MemAdr, + MemDin => MemDin, + MemDout => MemDout, + + -- 7-segment display +-- SEG => SEG, +-- DP => DP, +-- AN => AN, + + -- LEDs +-- LED => LED, + + -- Switches + SW => SW, + + -- Buttons + BTN => BTN, + SIN_FIRE => SIN_FIRE, + SIN_BOMB => SIN_BOMB, + + -- VGA connector + vgaRed => vgaRed, + vgaGreen => vgaGreen, + vgaBlue => vgaBlue, + Hsync => Hsync, + Vsync => Vsync, + + -- 12-pin connectors + JA => JA, + JB => JB, + + -- Sound board + PB => select_sound, + HAND => hand +); + +snd_rom : entity work.dpram +generic map( dWidth => 8, aWidth => 12) +port map( + clk_a => clock_snd, + addr_a => snd_addr, + q_a => snd_do, + clk_b => dl_clock, + we_b => snd_rom_we, + addr_b => dl_addr(11 downto 0), + d_b => dl_data +); + +snd_rom_we <= '1' when dl_wr = '1' and dl_addr(15 downto 12) = x"C" else '0'; -- C000-CFFF + +-- sound board +defender_sound_board : entity work.defender_sound_board +port map( + clk_0p89 => clock_snd, + reset => not cpu_reset_n, + hand => hand, + select_sound => select_sound, + audio_out => audio_out, + rom_addr => snd_addr, + rom_do => snd_do +); + +end Behavioral; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/sdram.sv b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/sdram.sv new file mode 100644 index 00000000..55c8b97d --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/sdram.sv @@ -0,0 +1,253 @@ +// +// sdram.v +// +// sdram controller implementation for the MiST board +// https://github.com/mist-devel/mist-board +// +// Copyright (c) 2013 Till Harbaum +// Copyright (c) 2019 Gyorgy Szombathelyi +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +module sdram ( + + // interface to the MT48LC16M16 chip + inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus + output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus + output reg SDRAM_DQML, // two byte masks + output reg SDRAM_DQMH, // two byte masks + output reg [1:0] SDRAM_BA, // two banks + output SDRAM_nCS, // a single chip select + output SDRAM_nWE, // write enable + output SDRAM_nRAS, // row address select + output SDRAM_nCAS, // columns address select + + // cpu/chipset interface + input init_n, // init signal after FPGA config to initialize RAM + input clk, // sdram clock + input clkref, + + input port1_req, + output reg port1_ack, + input port1_we, + input [23:1] port1_a, + input [1:0] port1_ds, + input [15:0] port1_d, + output [15:0] port1_q, + + input [17:1] cpu1_addr, + input [15:0] cpu1_d, + output reg [15:0] cpu1_q, + input cpu1_oe, + input cpu1_we, + input [1:0] cpu1_ds +); + +parameter MHZ = 80; // 80 MHz default clock, adjust to calculate the refresh rate correctly + +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz +localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8 +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd2; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + +// 64ms/8192 rows = 7.8us -> 842 cycles@108MHz +localparam RFRSH_CYCLES = 16'd78*MHZ/10; + +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +/* + SDRAM state machine + 1 word burst, CL2 +cmd issued registered + 0 RAS0 + 1 + 2 CAS0 + 3 + 4 + 5 + 6 data ready + 7 +*/ + +localparam STATE_RAS0 = 3'd0; // first state in cycle +localparam STATE_RAS1 = 3'd3; // Second ACTIVE command after RAS0 + tRRD (15ns) +localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY; // CAS phase - 3 +localparam STATE_READ0 = STATE_CAS0 + CAS_LATENCY + 2'd2; // 6 +localparam STATE_LAST = 3'd7; + +reg [2:0] t; + +always @(posedge clk) begin + reg clkref_d; + clkref_d <= clkref; + + t <= t + 1'd1; + if (t == STATE_LAST) t <= STATE_RAS0; + if (~clkref_d & clkref) t <= 3'd1; +end + +// --------------------------------------------------------------------- +// --------------------------- startup/reset --------------------------- +// --------------------------------------------------------------------- + +// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) +reg [4:0] reset; +reg init = 1'b1; +always @(posedge clk, negedge init_n) begin + if(!init_n) begin + reset <= 5'h1f; + init <= 1'b1; + end else begin + if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1; + init <= !(reset == 0); + end +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// all possible commands +localparam CMD_INHIBIT = 4'b1111; +localparam CMD_NOP = 4'b0111; +localparam CMD_ACTIVE = 4'b0011; +localparam CMD_READ = 4'b0101; +localparam CMD_WRITE = 4'b0100; +localparam CMD_BURST_TERMINATE = 4'b0110; +localparam CMD_PRECHARGE = 4'b0010; +localparam CMD_AUTO_REFRESH = 4'b0001; +localparam CMD_LOAD_MODE = 4'b0000; + +reg [3:0] sd_cmd; // current command sent to sd ram +reg [15:0] sd_din; +// drive control signals according to current command +assign SDRAM_nCS = sd_cmd[3]; +assign SDRAM_nRAS = sd_cmd[2]; +assign SDRAM_nCAS = sd_cmd[1]; +assign SDRAM_nWE = sd_cmd[0]; + +reg [24:1] addr_latch; +reg [24:1] addr_latch_next; +reg [15:0] din_latch; +reg oe_latch; +reg we_latch; +reg [1:0] ds; + +localparam PORT_NONE = 2'd0; +localparam PORT_CPU1 = 2'd1; +localparam PORT_REQ = 2'd2; + +reg [2:0] next_port; +reg [2:0] port; +reg port1_state; + +// PORT1 +always @(*) begin + if (port1_req ^ port1_state) begin + next_port = PORT_REQ; + addr_latch_next = { 1'b0, port1_a }; + end else if (cpu1_oe | cpu1_we) begin + next_port = PORT_CPU1; + addr_latch_next = { 7'd0, cpu1_addr }; + end else begin + next_port = PORT_NONE; + addr_latch_next = addr_latch; + end +end + +always @(posedge clk) begin + + // permanently latch ram data to reduce delays + sd_din <= SDRAM_DQ; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + { SDRAM_DQMH, SDRAM_DQML } <= 2'b11; + sd_cmd <= CMD_NOP; // default: idle + + if(init) begin + // initialization takes place at the end of the reset phase + if(t == STATE_RAS0) begin + + if(reset == 15) begin + sd_cmd <= CMD_PRECHARGE; + SDRAM_A[10] <= 1'b1; // precharge all banks + end + + if(reset == 10 || reset == 8) begin + sd_cmd <= CMD_AUTO_REFRESH; + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + SDRAM_A <= MODE; + SDRAM_BA <= 2'b00; + end + end + end else begin + // RAS phase + if(t == STATE_RAS0) begin + addr_latch <= addr_latch_next; + port <= next_port; + { oe_latch, we_latch } <= 2'b00; + + if (next_port != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[22:10]; + SDRAM_BA <= addr_latch_next[24:23]; + if (next_port == PORT_REQ) begin + { oe_latch, we_latch } <= { ~port1_we, port1_we }; + ds <= port1_ds; + din_latch <= port1_d; + port1_state <= port1_req; + end else begin + { oe_latch, we_latch } <= { cpu1_oe, cpu1_we }; + din_latch <= cpu1_d; + ds <= cpu1_ds; + end + end else begin + sd_cmd <= CMD_AUTO_REFRESH; + end + end + + // CAS phase + if(t == STATE_CAS0 && (we_latch || oe_latch)) begin + sd_cmd <= we_latch?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds; + if (we_latch) begin + SDRAM_DQ <= din_latch; + port1_ack <= port1_req; + end + SDRAM_A <= { 4'b0010, addr_latch[9:1] }; // auto precharge + SDRAM_BA <= addr_latch[24:23]; + end + + // Data returned + if(t == STATE_READ0 && oe_latch) begin + case(port) + PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end + PORT_CPU1: begin cpu1_q <= sd_din; end + default: ; + endcase; + end + end +end + +endmodule