Hi,
I was wondering if a replacement for the 8302 could be produced, as the orginal chip is becoming hard to find.
8302
-
- Font of All Knowledge
- Posts: 4653
- Joined: Mon Dec 20, 2010 11:40 am
- Location: Sunny Runcorn, Cheshire, UK
Re: 8302
I have the same question than Derek.
Could it be possible to reproduce it same as we do a replacement like Hermes?
I would like to try openhardware replacement for IC22, IC23
IC24 already has replacement and the HAL for Iss6 if I am not wrong also exist everyone can make its own one.
Also I have another question,
Why we doesn't use the value of R103 and R102 original instead to place a 0 Ohms on them?
Instead of it, it was described to solder on IC23 the two resistors of 33K and attach the common node to -12v rail...
Why is that recomended instead use their already footprint R102 & R103 and mood the PCB (if necessary to attach the common node to -12v Rail?
Thank you a lot
Could it be possible to reproduce it same as we do a replacement like Hermes?
I would like to try openhardware replacement for IC22, IC23
IC24 already has replacement and the HAL for Iss6 if I am not wrong also exist everyone can make its own one.
Also I have another question,
Why we doesn't use the value of R103 and R102 original instead to place a 0 Ohms on them?
Instead of it, it was described to solder on IC23 the two resistors of 33K and attach the common node to -12v rail...
Why is that recomended instead use their already footprint R102 & R103 and mood the PCB (if necessary to attach the common node to -12v Rail?
Thank you a lot
Re: 8302
What is the MIST implementation of the 8302?
Source https://github.com/mist-devel/ql/tree/master
Code: Select all
//
// zx8302.v
//
// ZX8302 for Sinclair QL for the MiST
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
// Copyright (c) 2021 Daniele Terdina
//
// 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 <http://www.gnu.org/licenses/>.
//
module zx8302 (
input clk, // 21 mhz
input clk_sys, // 27 MHz board clock
input reset,
input init,
// interrupts
output [1:0] ipl,
input xint,
// sdram interface for microdrive emulation
output [24:0] mdv_addr,
output [24:0] mdv2_addr,
input [15:0] mdv_din,
output mdv_read,
output mdv2_read,
input mdv_men,
input video_cycle,
// interface to watch MDV cartridge upload
input [24:0] mdv_dl_addr,
input mdv_download,
input mdv2_download,
output mdv_seldrive,
output mdv_active,
output led,
output audio,
// vertical synv
input vs,
// joysticks
input [4:0] js0,
input [4:0] js1,
input ps2_kbd_clk,
input ps2_kbd_data,
// bus interface
input clk_bus,
input cpu_sel,
input cpu_wr,
input [1:0] cpu_addr, // a[5,1]
input cpu_uds,
input cpu_lds,
input [15:0] cpu_din,
output [15:0] cpu_dout
);
// comdata shift register
wire ipc_comdata_in = comdata_reg[0];
reg [3:0] comdata_reg /* synthesis noprune */;
reg [1:0] ipc_busy;
reg comdata_to_cpu;
reg prev_ipc_comctrl;
// ---------------------------------------------------------------------------------
// ----------------------------- CPU register write --------------------------------
// ---------------------------------------------------------------------------------
reg [7:0] mctrl;
// cpu is writing io registers
always @(negedge clk_bus) begin
if (reset) begin
comdata_reg <= 4'b0000;
ipc_busy <= 2'b11;
end
irq_ack <= 5'd0;
// cpu writes to 0x18XXX area
if(cpu_sel && cpu_wr) begin
// even addresses have uds asserted and use the upper 8 data bus bits
if(cpu_uds) begin
// cpu writes microdrive control register
if(cpu_addr == 2'b10)
mctrl <= cpu_din[15:8];
end
// odd addresses have lds asserted and use the lower 8 data bus bits
if(cpu_lds) begin
// 18003 - IPCWR
// (host sends a single bit to ipc)
if(cpu_addr == 2'b01) begin
// data is ----XEDS
// S = start bit (should be 0)
// D = data bit (0/1)
// E = stop bit (should be 1)
// X = extra stopbit (should be 1)
comdata_reg <= cpu_din[3:0];
ipc_busy <= 2'b11; // Show IPC BUSY until the IPC asserts COMCTL twice
end
// cpu writes interrupt register
if(cpu_addr == 2'b10) begin
irq_mask <= cpu_din[7:5];
irq_ack <= cpu_din[4:0];
end
end
end
if (!ipc_comctrl && prev_ipc_comctrl) begin
comdata_to_cpu <= zx8302_comdata_in; // Latch COMDATA since the IPC will quickly reset it to 1 when sending data
comdata_reg <= { 1'b1, comdata_reg[3:1] };
ipc_busy <= { 1'b0, ipc_busy[1] };
end
prev_ipc_comctrl <= ipc_comctrl;
end
// ---------------------------------------------------------------------------------
// ----------------------------- CPU register read ---------------------------------
// ---------------------------------------------------------------------------------
// status register read
// bit 0 Network port
// bit 1 Transmit buffer full
// bit 2 Receive buffer full
// bit 3 Microdrive GAP
// bit 4 SER1 DTR
// bit 5 SER2 CTS
// bit 6 IPC busy
// bit 7 COMDATA
wire [7:0] io_status = { comdata_to_cpu, ipc_busy[0], 2'b00,
(mdv_seldrive?mdv2_gap:mdv_gap),
(mdv_seldrive?mdv2_rx_ready:mdv_rx_ready),
(mdv_seldrive?mdv2_tx_empty:mdv_tx_empty), 1'b0 };
assign cpu_dout =
// 18000/18001 and 18002/18003
(cpu_addr == 2'b00)?rtc[47:32]:
(cpu_addr == 2'b01)?rtc[31:16]:
// 18020/18021 and 18022/18023
(cpu_addr == 2'b10)?{io_status, irq_pending}:
(cpu_addr == 2'b11)?(mdv_seldrive?{mdv2_byte, mdv2_byte}:{mdv_byte, mdv_byte}):
16'h0000;
// ---------------------------------------------------------------------------------
// -------------------------------------- IPC --------------------------------------
// ---------------------------------------------------------------------------------
wire ipc_comctrl;
wire ipc_comdata_out;
// 8302 sees its own comdata as well as the one from the ipc
wire zx8302_comdata_in = ipc_comdata_in && ipc_comdata_out;
wire [1:0] ipc_ipl;
ipc ipc (
.reset ( reset ),
.clk_sys ( clk_sys ), // 27 MHz board clock
.comctrl ( ipc_comctrl ),
.comdata_in ( ipc_comdata_in ),
.comdata_out ( ipc_comdata_out),
.audio ( audio ),
.ipl ( ipc_ipl ),
.js0 ( js0 ),
.js1 ( js1 ),
.ps2_kbd_clk ( ps2_kbd_clk ),
.ps2_kbd_data ( ps2_kbd_data )
);
// ---------------------------------------------------------------------------------
// -------------------------------------- IRQs -------------------------------------
// ---------------------------------------------------------------------------------
wire [7:0] irq_pending = {1'b0, (mdv_sel == 0), clk64k, xint_irq, vsync_irq, 1'b0, 1'b0, gap_irq };
reg [2:0] irq_mask;
reg [4:0] irq_ack;
// any pending irq raises ipl to 2 and the ipc can control both ipl lines
assign ipl = { ipc_ipl[1] && (irq_pending[4:0] == 0), ipc_ipl[0] };
// vsync irq is set whenever vsync rises
reg vsync_irq;
wire vsync_irq_reset = reset || irq_ack[3];
always @(posedge clk) begin
reg old_vs;
old_vs <= vs;
if(vsync_irq_reset) vsync_irq <= 1'b0;
else if(~old_vs & vs) vsync_irq <= 1'b1;
end
// toggling the mask will also trigger irqs ...
wire gap_irq_in = (mdv_seldrive?mdv2_gap:mdv_gap) && irq_mask[0];
reg gap_irq;
wire gap_irq_reset = reset || irq_ack[0];
always @(posedge clk) begin
reg old_irq;
old_irq <= gap_irq_in;
if(gap_irq_reset) gap_irq <= 1'b0;
else if(~old_irq & gap_irq_in) gap_irq <= 1'b1;
end
// toggling the mask will also trigger irqs ...
wire xint_irq_in = xint && irq_mask[2];
reg xint_irq;
wire xint_irq_reset = reset || irq_ack[4];
always @(posedge clk) begin
reg old_irq;
old_irq <= xint_irq_in;
if(xint_irq_reset) xint_irq <= 1'b0;
else if(~old_irq & xint_irq_in) xint_irq <= 1'b1;
end
// ---------------------------------------------------------------------------------
// ----------------------------------- microdrive ----------------------------------
// ---------------------------------------------------------------------------------
wire mdv_gap;
wire mdv2_gap;
wire mdv_tx_empty;
wire mdv2_tx_empty;
wire mdv_rx_ready;
wire mdv2_rx_ready;
wire [7:0] mdv_byte;
wire [7:0] mdv2_byte;
assign led = !(mdv_sel[0] || mdv_sel[1]);
mdv mdv (
.clk ( clk ),
.reset ( init ),
.mdv_drive (1), //This is MDV1_
.sel ( mdv_sel[0] ),
// control bits
.gap ( mdv_gap ),
.tx_empty ( mdv_tx_empty ),
.rx_ready ( mdv_rx_ready ),
.dout ( mdv_byte ),
.download ( mdv_download ),
.dl_addr ( mdv_dl_addr ),
// ram interface to read image
.mem_ena ( mdv_men ),
.mem_cycle( video_cycle ),
.mem_clk ( clk_bus ),
.mem_addr ( mdv_addr ),
.mem_read ( mdv_read ),
.mem_din ( mdv_din )
);
mdv mdv2 (
.clk ( clk ),
.reset ( init ),
.mdv_drive ( 2 ), //This is MDV2_
.sel ( mdv_sel[1] ),
// control bits
.gap ( mdv2_gap ),
.tx_empty ( mdv2_tx_empty ),
.rx_ready ( mdv2_rx_ready ),
.dout ( mdv2_byte ),
.download ( mdv2_download ),
.dl_addr ( mdv_dl_addr ),
// ram interface to read image
.mem_ena ( mdv_men ),
.mem_cycle( video_cycle ),
.mem_clk ( clk_bus ),
.mem_addr ( mdv2_addr ),
.mem_read ( mdv2_read ),
.mem_din ( mdv_din )
);
// the microdrive control register mctrl generates the drive selection
// mdv_sel = 1 for mdv1_, mdv_sel = 2 for mdv2_
reg [7:0] mdv_sel;
always @(posedge clk) begin
reg old_mctrl;
old_mctrl <= mctrl[1];
if(old_mctrl & ~mctrl[1]) mdv_sel <= { mdv_sel[6:0], mctrl[0] };
end
// 0 for MDV1_ or nothing and 1 for MDV2_
// Only one microdrive can be accessed at a time, this allows
// switching between them.
assign mdv_seldrive = mdv_sel[1]?1'b1:1'b0;
assign mdv_active = mdv_sel[1] || mdv_sel[0];
// ---------------------------------------------------------------------------------
// -------------------------------------- RTC --------------------------------------
// ---------------------------------------------------------------------------------
// PLL for the real time clock (rtc)
reg [47:0] rtc;
always @(posedge clk64k)
rtc <= rtc + 48'd1;
wire clk64k;
pll_rtc pll_rtc (
.inclk0(clk_sys),
.c0(clk64k) // 65536Hz
);
endmodule
Re: 8302
Wau! amazing!bwinkel67 wrote: Thu Jun 13, 2024 7:36 pm What is the MIST implementation of the 8302?
Source https://github.com/mist-devel/ql/tree/masterCode: Select all
// // zx8302.v ... endmodule
Thank you, the code looks pretty good for understanding.
I 'm going to study it.
Edit: it says MDVs emulation (QLay format), what does it mean?
Whatever it is a good point to start

-
- Font of All Knowledge
- Posts: 4653
- Joined: Mon Dec 20, 2010 11:40 am
- Location: Sunny Runcorn, Cheshire, UK
Re: 8302
The code in the mister FPGA does just enough to 'mimic' a Microdrive interface, and provide a rudimentary seconds counter RTC, but don't be fooled - there is a lot that's not supported here - not sure if the QL network interface is implemented in the mister hardware? Certainly the serial port (transmit side) is not implemented, nor all the timing logic for the Microdrives themselves
Re: 8302
Yeah, I figured as much when it talked about emulated MDV images. But it may be a start for someone that has the skill set. Plus, maybe Charlie has some insights regarding the MDV stuff since he did recreate the Spectrum's Interface 1 ULA. Could this also be done the PiStorm approach via a CPLD/RaPi model so the 8302 implementation is more at a software level?