1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-02-06 08:04:41 +00:00

[QL] Added second microdrive support. ROM now selectable.

This commit is contained in:
Squid
2021-06-27 16:28:04 +01:00
parent fbaaaab06f
commit be79d85fcb
4 changed files with 91 additions and 21 deletions

View File

@@ -83,7 +83,9 @@ always@(posedge sck, posedge ss) begin
if(sdi) begin
// download rom to address 0, microdrive image to 16MB+
if(index == 0) laddr <= 25'h0 - 25'd1;
else laddr <= 25'h800000 - 25'd1;
if(index == 1) laddr <= 25'h800000 - 25'd1; //mdv1_
if(index == 2) laddr <= 25'h900000 - 25'd1; //mdv2_
if(index == 3) laddr <= 25'h0 - 25'd1; //Additional ROM bios selection
downloading_reg <= 1'b1;
end else

View File

@@ -25,8 +25,10 @@ module mdv (
input reset,
input reverse,
input sel,
input mdv_drive,
input sel, // select microdrive 1 or 2
// control bits
output gap,
@@ -46,8 +48,9 @@ module mdv (
input [15:0] mem_din
);
localparam BASE_ADDR = 25'h800000;
// mdv1_ image stored at h800000, mdv2_ image stored at address h900000
wire [24:0] BASE_ADDR = (mdv_drive == 1)?25'h800000:25'h900000;
// a gap is permanently present if no mdv is inserted or if
// there's a gap on the inserted one. This is the signal that triggers
// the irq and can be seen by the cpu
@@ -118,7 +121,7 @@ always @(posedge mdv_clk) begin
mdv_bit_cnt <= mdv_bit_cnt + 4'd1;
if(mdv_bit_cnt == 15) begin
mdv_data <= mdv_din;
mdv_data_valid <= !mdv_gap_active &&
mdv_data_valid <= !mdv_gap_active &&
// don't generate data_valid for first 12 bytes (preamble)
(mdv_gap_cnt > 5) &&
// and also not for the sector internal preamble
@@ -126,8 +129,9 @@ always @(posedge mdv_clk) begin
mdv_next_word <= 1'b1;
// reset counters when address is out of range
if((mem_addr > mdv_end)||(mem_addr < 25'h800000)) begin
// reset counters when address is out of range
if((mem_addr > mdv_end)||(mem_addr < BASE_ADDR)) begin
mem_addr <= BASE_ADDR;
// assume we start at the end of a post-sector/pre-header gap

View File

@@ -70,7 +70,9 @@ module ql (
// it to control the menu on the OSD
parameter CONF_STR = {
"QL;;",
"F1,MDV;",
"F,MDV,Load MDV1;",
"F,MDV,Load MDV2;",
"F,ROM;",
"O2,MDV direction,normal,reverse;",
"O3,RAM,128k,640k;",
"O4,Video mode,PAL,NTSC;",
@@ -78,7 +80,7 @@ parameter CONF_STR = {
"T6,Reset"
};
parameter CONF_STR_LEN = 4+7+32+17+23+20+8;
parameter CONF_STR_LEN = 4+16+16+6+32+17+23+20+8;
// the status register is controlled by the on screen display (OSD)
wire [7:0] status;
@@ -206,8 +208,10 @@ wire sys_wr = dio_download?dio_write:(cpu_wr && cpu_ram);
wire sys_oe = dio_download?1'b0:(cpu_rd && cpu_mem);
// microdrive emulation and video share the video cycle time slot
wire [24:0] video_cycle_addr = mdv_read?mdv_addr:{6'd0, video_addr};
wire video_cycle_rd = mdv_read?1'b1:video_rd;
// only one drive at a time is accessed
wire [24:0] video_cycle_addr = (mdv_read || mdv2_read)?(mdv_seldrive?mdv2_addr:mdv_addr):{6'd0, video_addr};
wire video_cycle_rd = (mdv_read || mdv2_read)?1'b1:video_rd;
// video and CPU/data_io time share the sdram bus
wire [24:0] sdram_addr = video_cycle?video_cycle_addr:sys_addr;
@@ -352,7 +356,7 @@ osd #(12,0,5) osd (
// -------------------------------------- reset ------------------------------------
// ---------------------------------------------------------------------------------
wire rom_download = dio_download && (dio_index == 0);
wire rom_download = dio_download && (dio_index == 0 || dio_index == 3);
reg [11:0] reset_cnt;
wire reset = (reset_cnt != 0);
always @(posedge clk2) begin
@@ -370,10 +374,15 @@ wire zx8302_sel = cpu_cycle && cpu_io && !cpu_addr[6];
wire [1:0] zx8302_addr = {cpu_addr[5], cpu_addr[1]};
wire [15:0] zx8302_dout;
wire mdv_download = (dio_index == 1) && dio_download;
wire mdv_men;
wire mdv_download = (dio_index == 1) && dio_download; //signal for active download from SD
wire mdv2_download = (dio_index == 2) && dio_download; //signal for active download from SD
wire mdv_men; //signal telling mdv emulation that it may use the video
wire mdv_read;
wire mdv2_read;
wire [24:0] mdv_addr;
wire [24:0] mdv2_addr;
wire mdv_seldrive; //1 for MDV2_ active, 0 for MDV1_ active or nothing
wire audio;
assign AUDIO_L = audio;
@@ -397,7 +406,7 @@ zx8302 zx8302 (
.cpu_addr ( zx8302_addr ),
.cpu_ds ( cpu_ds ),
.cpu_din ( cpu_dout ),
.cpu_dout ( zx8302_dout ),
.cpu_dout ( zx8302_dout ),
// joysticks
.js0 ( js0[4:0] ),
@@ -410,15 +419,22 @@ zx8302 zx8302 (
// microdrive sdram interface
.mdv_addr ( mdv_addr ),
.mdv2_addr ( mdv2_addr ),
.mdv_din ( sdram_dout ),
.mdv_read ( mdv_read ),
.mdv2_read ( mdv2_read ),
.mdv_men ( mdv_men ),
.video_cycle ( video_cycle ),
.mdv_reverse ( status[2] ),
.mdv_download ( mdv_download ),
.mdv2_download ( mdv2_download ),
.mdv_seldrive ( mdv_seldrive) ,
.mdv_dl_addr ( dio_addr )
);
// ---------------------------------------------------------------------------------

View File

@@ -32,14 +32,19 @@ module zx8302 (
// 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,
input mdv_reverse,
output led,
@@ -127,8 +132,10 @@ end
// bit 7 COMDATA
wire [7:0] io_status = { zx8302_comdata_in, ipc_busy, 2'b00,
mdv_gap, mdv_rx_ready, mdv_tx_empty, 1'b0 };
(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]:
@@ -136,7 +143,7 @@ assign cpu_dout =
// 18020/18021 and 18022/18023
(cpu_addr == 2'b10)?{io_status, irq_pending}:
(cpu_addr == 2'b11)?{mdv_byte, mdv_byte}:
(cpu_addr == 2'b11)?(mdv_seldrive?{mdv2_byte, mdv2_byte}:{mdv_byte, mdv_byte}):
16'h0000;
@@ -213,7 +220,7 @@ always @(posedge vs or posedge vsync_irq_reset) begin
end
// toggling the mask will also trigger irqs ...
wire gap_irq_in = mdv_gap && irq_mask[0];
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 gap_irq_in or posedge gap_irq_reset) begin
@@ -236,16 +243,22 @@ end
// ---------------------------------------------------------------------------------
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];
assign led = !(mdv_sel[0] || mdv_sel[1]);
mdv mdv (
.clk ( clk ),
.reset ( init ),
.mdv_drive (1), //This is MDV1_
.sel ( mdv_sel[0] ),
.reverse ( mdv_reverse ),
@@ -268,12 +281,47 @@ mdv mdv (
.mem_din ( mdv_din )
);
mdv mdv2 (
.clk ( clk ),
.reset ( init ),
.mdv_drive ( 2 ), //This is MDV2_
.sel ( mdv_sel[1] ),
.reverse ( mdv_reverse ),
// 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 @(negedge mctrl[1])
mdv_sel <= { mdv_sel[6:0], mctrl[0] };
// 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;
// ---------------------------------------------------------------------------------
// -------------------------------------- RTC --------------------------------------
// ---------------------------------------------------------------------------------