391 lines
13 KiB
Systemverilog
391 lines
13 KiB
Systemverilog
/******************************************************************************
|
|
* SE-Exp30 MacSE Accelerator
|
|
* techav
|
|
* 2021-03-20
|
|
* Processor Accelerator System Translation Engine
|
|
******************************************************************************
|
|
* Handles all logic to translate the Mac SE 68000 PDS bus to the 68030 bus as
|
|
* well as additional logic for interfacing with the 68882 FPU.
|
|
*****************************************************************************/
|
|
|
|
module paste (
|
|
inout wire ncpuReset, // 68030 reset signal (tristate)
|
|
inout wire ncpuHalt, // 68030 halt signal (tristate)
|
|
input wire ncpuDS, // 68030 data strobe signal
|
|
input wire ncpuAS, // 68030 address strobe signal
|
|
inout wire ncpuDsack0, // 68030 DS Ack 0 signal
|
|
inout wire ncpuDsack1, // 68030 DS Ack 1 signal
|
|
input wire cpuSize0, // 68030 Size 0 signal
|
|
input wire cpuSize1, // 68030 Size 1 signal
|
|
input wire cpuA0, // 68030 Address 0 signal
|
|
input logic [23:20] cpuAddrHi, // 68030 Address Hi (16MB) signals
|
|
input logic [19:13] cpuAddrMid, // 68030 Address Mid (FPU decode) signals
|
|
output wire ncpuAvec, // 68030 Autovector request signal
|
|
input logic [2:0] cpuFC, // 68030 Function Code signals
|
|
input wire cpuClock, // 68030 Primary CPU Clock signal
|
|
input wire cpuRnW, // 68030 Read/Write signal
|
|
input wire ncpuBG, // 68030 Bus Grant signal
|
|
inout wire ncpuBerr, // 68030 Bus Error signal
|
|
inout wire ncpuCiin, // 68030 Cache Inhibit signal
|
|
input wire npdsReset, // PDS Reset signal
|
|
inout wire npdsLds, // PDS Lower Data Strobe signal
|
|
inout wire npdsUds, // PDS Upper Data Strobe signal
|
|
inout wire npdsAs, // PDS Address Strobe signal
|
|
input wire npdsDtack, // PDS Data Xfer Ack signal
|
|
input wire npdsBg, // PDS Bus Grant signal
|
|
output wire npdsBGack, // PDS Bus Grant Ack signal
|
|
output wire npdsBr, // PDS Bus Request signal
|
|
inout wire npdsVma, // PDS Valid Memory Addr signal
|
|
input wire npdsVpa, // PDS Valid Peripheral Addr signal
|
|
input wire pdsC8m, // PDS 8MHz System Clock signal
|
|
input wire pdsClockE, // PDS 800kHz 6800 bus E clock
|
|
output wire nbufDhiEn, // Data buffer CPU[31:24] <=> PDS[15:8]
|
|
output wire nbufDlo1En, // Data buffer CPU[23:16] <=> PDS[7:0]
|
|
output wire nbufDlo2En, // Data buffer CPU[31:24] <=> PDS[7:0]
|
|
output wire bufDDir, // Data buffer direction
|
|
output wire nbufCEn, // Control signal buffer enable
|
|
output wire nbufAEn, // Address buffer enable
|
|
input wire nfpuSense, // FPU Presence Detect signal
|
|
output wire nfpuCe // FPU Chip Select signal
|
|
);
|
|
|
|
// define state machine states
|
|
parameter
|
|
S0 = 0,
|
|
S1 = 1,
|
|
S2 = 2,
|
|
S3 = 3,
|
|
S4 = 4,
|
|
S5 = 5,
|
|
S6 = 6,
|
|
S7 = 7,
|
|
S8 = 8;
|
|
|
|
logic [3:0] busState; // state machine for 68000 bus
|
|
logic [1:0] termState; // state machine for 68030 bus termination
|
|
logic [1:0] resetgenState; // state machine for nCpuReset generator
|
|
logic [1:0] cycleEndState; // state machine for 68030 bus cycle end monitor
|
|
|
|
wire nUD, nLD; // intermediate data strobe signals
|
|
|
|
// 68000 bus state machine
|
|
// synchronous to 8MHz 68000 clock
|
|
always @(posedge pdsC8m or negedge npdsReset) begin
|
|
if(npdsReset == 0) busState <= S0;
|
|
else begin
|
|
case(busState)
|
|
S0 : begin
|
|
// idle state, wait for cpu to begin bus cycle
|
|
if(ncpuAS == 0) busState <= S1;
|
|
else busState <= S0;
|
|
end
|
|
S1 : begin
|
|
// 68000 bus cycle state 2/3
|
|
// progress immediately
|
|
busState <= S2;
|
|
end
|
|
S2 : begin
|
|
// 68000 bus cycle state 4/5
|
|
// wait for PDS DTACK or PDS VPA
|
|
if(npdsDtack == 0) busState <= S3;
|
|
else if(npdsVpa == 0) busState <= S4;
|
|
else busState <= S2;
|
|
end
|
|
S3 : begin
|
|
// 68000 bus cycle state 6/7
|
|
// end 68000 bus cycle
|
|
// wait for cycleEndState == S2
|
|
if(cycleEndState == S2) busState <= S0;
|
|
else busState <= S3;
|
|
end
|
|
S4 : begin
|
|
// 6800 bus cycle state 1
|
|
// wait for E clock = 0
|
|
if(pdsClockE == 0) busState <= S5;
|
|
else busState <= S4;
|
|
end
|
|
S5 : begin
|
|
// 6800 bus cycle state 2
|
|
// wait for E clock = 1
|
|
if(pdsClockE == 1) busState <= S6;
|
|
else busState <= S5;
|
|
end
|
|
S6 : begin
|
|
// 6800 bus cycle state 3
|
|
// progress immediately
|
|
busState <= S7;
|
|
end
|
|
S7 : begin
|
|
// 6800 bus cycle state 4
|
|
// progress immediately
|
|
busState <= S8;
|
|
end
|
|
S8 : begin
|
|
// 6800 bus cycle state 5
|
|
// wait for cycleEndState == S2
|
|
if(cycleEndState == S2) busState <= S0;
|
|
else busState <= S8;
|
|
end
|
|
default: begin
|
|
// how did we end up here?
|
|
busState <= S0;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
// 68030 bus termination state machine
|
|
// drives CPU DSACKx signals
|
|
// synchronous to CPU clock
|
|
always @(posedge cpuClock or negedge npdsReset) begin
|
|
if(npdsReset == 0) termState <= S0;
|
|
else begin
|
|
case(termState)
|
|
S0 : begin
|
|
// idle, wait for busState
|
|
if(busState == S3 && pdsC8m == 1) termState <= S1;
|
|
else if(busState == S8 && pdsC8m == 1) termState <= S1;
|
|
else termState <= S0;
|
|
end
|
|
S1 : begin
|
|
// assert 68030 bus termination
|
|
// progress immediately
|
|
termState <= S2;
|
|
end
|
|
S2 : begin
|
|
// wait for busState
|
|
if(busState == S0) termState <= S0;
|
|
else termState <= S2;
|
|
end
|
|
default: begin
|
|
// how did we end up here?
|
|
termState <= S0;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
// 68030 bus cycle end monitor
|
|
// watches for 68030 ending a bus cycle (de-asserting AS)
|
|
// synchronous to CPU clock
|
|
always @(posedge cpuClock or negedge npdsReset) begin
|
|
if(npdsReset == 0) cycleEndState <= S0;
|
|
else begin
|
|
case(cycleEndState)
|
|
S0 : begin
|
|
if(busState != S0) cycleEndState <= S1;
|
|
else cycleEndState <= S0;
|
|
end
|
|
S1 : begin
|
|
if(ncpuAS == 1) cycleEndState <= S2;
|
|
else cycleEndState <= S1;
|
|
end
|
|
S2: begin
|
|
if(busState == S0) cycleEndState <= S0;
|
|
else cycleEndState <= S2;
|
|
end
|
|
default: begin
|
|
// how did get end up here?
|
|
cycleEndState <= S0;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
// state machine for power on reset
|
|
always @(posedge cpuClock or negedge npdsReset) begin
|
|
// sync state machine clocked by primary CPU clock with async reset
|
|
if(npdsReset == 1'b0) begin
|
|
resetgenState <= S0;
|
|
end else begin
|
|
case(resetgenState)
|
|
S0 : begin
|
|
// wait for deassertion of npdsReset
|
|
if(npdsReset == 1'b1) begin
|
|
resetgenState <= S1;
|
|
end else begin
|
|
// shouldn't actually end up here
|
|
resetgenState <= S0;
|
|
end
|
|
end
|
|
S1 : begin
|
|
// wait for Bus Grant from SE
|
|
if(npdsBg == 1'b0) begin
|
|
resetgenState <= S2;
|
|
end else begin
|
|
resetgenState <= S1;
|
|
end
|
|
end
|
|
S2 : begin
|
|
// this is actually our idle state.
|
|
// stay here until the system resets again.
|
|
if(npdsReset == 1'b1) begin
|
|
resetgenState <= S2;
|
|
end else begin
|
|
resetgenState <= S0;
|
|
end
|
|
end
|
|
default: begin
|
|
// really shouldn't be here
|
|
resetgenState <= S0;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
// combinatorial logic
|
|
assign nUD = ~(~cpuA0 || cpuRnW);
|
|
assign nLD = ~(cpuA0 || ~cpuSize0 || cpuSize1 || cpuRnW);
|
|
|
|
always_comb begin
|
|
// CPU reset signals
|
|
if(resetgenState != S2) begin
|
|
ncpuReset <= 1'b0;
|
|
ncpuHalt <= 1'b0;
|
|
end else begin
|
|
ncpuReset <= 1'bz;
|
|
ncpuHalt <= 1'bz;
|
|
end
|
|
|
|
// bus request & grant
|
|
if(resetgenState == S0) begin
|
|
npdsBr <= 1'bz;
|
|
end else begin
|
|
npdsBr <= 1'b0;
|
|
end
|
|
if(resetgenState == S2) begin
|
|
npdsBGack <= 1'b0;
|
|
end else begin
|
|
npdsBGack <= 1'bz;
|
|
end
|
|
|
|
// buffer enable signals
|
|
if(ncpuBG == 1'b1) begin
|
|
if(nUD == 0 && npdsBg == 0) begin
|
|
nbufDhiEn <= 1'b0;
|
|
end else begin
|
|
nbufDhiEn <= 1'b1;
|
|
end
|
|
if(nLD == 0 && nUD == 1 && npdsBg == 0) begin
|
|
nbufDlo2En <= 1'b0;
|
|
end else begin
|
|
nbufDlo2En <= 1'b1;
|
|
end
|
|
if(nLD == 0 && nUD == 0 && npdsBg == 0) begin
|
|
nbufDlo1En <= 1'b0;
|
|
end else begin
|
|
nbufDlo1En <= 1'b1;
|
|
end
|
|
if(npdsBg <= 1'b0) begin
|
|
nbufAEn <= 1'b0;
|
|
nbufCEn <= 1'b0;
|
|
end else begin
|
|
nbufAEn <= 1'b1;
|
|
nbufCEn <= 1'b1;
|
|
end
|
|
end else begin
|
|
nbufDhiEn <= 1'b1;
|
|
nbufDlo2En <= 1'b1;
|
|
nbufDlo1En <= 1'b1;
|
|
nbufAEn <= 1'b1;
|
|
nbufCEn <= 1'b1;
|
|
end
|
|
|
|
// data buffer direction
|
|
bufDDir <= cpuRnW;
|
|
|
|
// CPU cache inhibit
|
|
if(cpuAddrHi >= 4'h6) begin
|
|
ncpuCiin <= 1'b0;
|
|
end else begin
|
|
ncpuCiin <= 1'bz;
|
|
end
|
|
|
|
// Upper/Lower data strobes
|
|
if(npdsBg == 1) begin
|
|
npdsUds <= 1'bZ;
|
|
npdsLds <= 1'bZ;
|
|
end else begin
|
|
if(cpuRnW == 1 && busState == S1) begin
|
|
npdsUds <= nUD;
|
|
npdsLds <= nLD;
|
|
end else if (busState == S2 || busState == S3 ||
|
|
busState == S4 || busState == S5 ||
|
|
busState == S6 || busState == S7 ||
|
|
busState == S8) begin
|
|
npdsUds <= nUD;
|
|
npdsLds <= nLD;
|
|
end else begin
|
|
npdsUds <= 1;
|
|
npdsLds <= 1;
|
|
end
|
|
end
|
|
|
|
// Address strobe
|
|
if(npdsBg == 1) npdsAs <= 1'bZ;
|
|
else begin
|
|
if(busState != S0) npdsAs <= 0;
|
|
else npdsAs <= 1;
|
|
end
|
|
|
|
// 6800 bus VMA signal
|
|
if(npdsBg == 1) npdsVma <= 1'bZ;
|
|
else begin
|
|
if(busState == S5 || busState == S6 ||
|
|
busState == S7 || busState == S8) begin
|
|
npdsVma <= 0;
|
|
end else npdsVma <= 1;
|
|
end
|
|
|
|
// 68030 bus termination signals
|
|
// FPU will terminate on its own
|
|
if(termState == S1) begin
|
|
if(cpuAddrHi < 4'h5 && cpuFC < 3'h7) begin
|
|
// RAM/ROM access - 16-bit
|
|
ncpuDsack0 <= 1'bZ;
|
|
ncpuDsack1 <= 0;
|
|
ncpuAvec <= 1'bZ;
|
|
ncpuBerr <= 1'bZ;
|
|
end else if(cpuAddrHi >= 4'h5 && cpuFC < 3'h7) begin
|
|
// peripheral access - 8-bit
|
|
ncpuDsack0 <= 0;
|
|
ncpuDsack1 <= 1'bZ;
|
|
ncpuAvec <= 1'bZ;
|
|
ncpuBerr <= 1'bZ;
|
|
end else if(cpuFC == 3'h7) begin
|
|
// autovector interrupt
|
|
ncpuAvec <= 0;
|
|
ncpuDsack0 <= 1'bZ;
|
|
ncpuDsack1 <= 1'bZ;
|
|
ncpuBerr <= 1'bZ;
|
|
end else begin
|
|
// this is an odd case. how did it happen?
|
|
// may as well throw an error
|
|
ncpuBerr <= 0;
|
|
ncpuDsack0 <= 1'bZ;
|
|
ncpuDsack1 <= 1'bZ;
|
|
ncpuAvec <= 1'bZ;
|
|
end
|
|
end else begin
|
|
ncpuBerr <= 1'bZ;
|
|
ncpuDsack0 <= 1'bZ;
|
|
ncpuDsack1 <= 1'bZ;
|
|
ncpuAvec <= 1'bZ;
|
|
end
|
|
|
|
// FPU chip enable & presence detect
|
|
if(cpuAddrMid == 7'h11 && cpuFC == 3'h7 && ncpuAS) begin
|
|
nfpuCe <= 1'b0;
|
|
if(nfpuSense == 1'b1) begin
|
|
// pulled high means FPU missing. assert bus error
|
|
ncpuBerr <= 1'b0;
|
|
end else begin
|
|
ncpuBerr <= 1'bz;
|
|
end
|
|
end else begin
|
|
nfpuCe <= 1'b1;
|
|
ncpuBerr <= 1'bz;
|
|
end
|
|
end
|
|
|
|
endmodule |