mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-05-01 22:26:59 +00:00
[QL] Added second microdrive support. ROM now selectable.
This commit is contained in:
@@ -83,7 +83,9 @@ always@(posedge sck, posedge ss) begin
|
|||||||
if(sdi) begin
|
if(sdi) begin
|
||||||
// download rom to address 0, microdrive image to 16MB+
|
// download rom to address 0, microdrive image to 16MB+
|
||||||
if(index == 0) laddr <= 25'h0 - 25'd1;
|
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;
|
downloading_reg <= 1'b1;
|
||||||
end else
|
end else
|
||||||
|
|||||||
@@ -25,8 +25,10 @@ module mdv (
|
|||||||
input reset,
|
input reset,
|
||||||
|
|
||||||
input reverse,
|
input reverse,
|
||||||
|
|
||||||
input sel,
|
input mdv_drive,
|
||||||
|
|
||||||
|
input sel, // select microdrive 1 or 2
|
||||||
|
|
||||||
// control bits
|
// control bits
|
||||||
output gap,
|
output gap,
|
||||||
@@ -46,8 +48,9 @@ module mdv (
|
|||||||
input [15:0] mem_din
|
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
|
// 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
|
// there's a gap on the inserted one. This is the signal that triggers
|
||||||
// the irq and can be seen by the cpu
|
// 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;
|
mdv_bit_cnt <= mdv_bit_cnt + 4'd1;
|
||||||
if(mdv_bit_cnt == 15) begin
|
if(mdv_bit_cnt == 15) begin
|
||||||
mdv_data <= mdv_din;
|
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)
|
// don't generate data_valid for first 12 bytes (preamble)
|
||||||
(mdv_gap_cnt > 5) &&
|
(mdv_gap_cnt > 5) &&
|
||||||
// and also not for the sector internal preamble
|
// and also not for the sector internal preamble
|
||||||
@@ -126,8 +129,9 @@ always @(posedge mdv_clk) begin
|
|||||||
|
|
||||||
mdv_next_word <= 1'b1;
|
mdv_next_word <= 1'b1;
|
||||||
|
|
||||||
// reset counters when address is out of range
|
// reset counters when address is out of range
|
||||||
if((mem_addr > mdv_end)||(mem_addr < 25'h800000)) begin
|
if((mem_addr > mdv_end)||(mem_addr < BASE_ADDR)) begin
|
||||||
|
|
||||||
mem_addr <= BASE_ADDR;
|
mem_addr <= BASE_ADDR;
|
||||||
|
|
||||||
// assume we start at the end of a post-sector/pre-header gap
|
// assume we start at the end of a post-sector/pre-header gap
|
||||||
|
|||||||
@@ -70,7 +70,9 @@ module ql (
|
|||||||
// it to control the menu on the OSD
|
// it to control the menu on the OSD
|
||||||
parameter CONF_STR = {
|
parameter CONF_STR = {
|
||||||
"QL;;",
|
"QL;;",
|
||||||
"F1,MDV;",
|
"F,MDV,Load MDV1;",
|
||||||
|
"F,MDV,Load MDV2;",
|
||||||
|
"F,ROM;",
|
||||||
"O2,MDV direction,normal,reverse;",
|
"O2,MDV direction,normal,reverse;",
|
||||||
"O3,RAM,128k,640k;",
|
"O3,RAM,128k,640k;",
|
||||||
"O4,Video mode,PAL,NTSC;",
|
"O4,Video mode,PAL,NTSC;",
|
||||||
@@ -78,7 +80,7 @@ parameter CONF_STR = {
|
|||||||
"T6,Reset"
|
"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)
|
// the status register is controlled by the on screen display (OSD)
|
||||||
wire [7:0] status;
|
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);
|
wire sys_oe = dio_download?1'b0:(cpu_rd && cpu_mem);
|
||||||
|
|
||||||
// microdrive emulation and video share the video cycle time slot
|
// microdrive emulation and video share the video cycle time slot
|
||||||
wire [24:0] video_cycle_addr = mdv_read?mdv_addr:{6'd0, video_addr};
|
// only one drive at a time is accessed
|
||||||
wire video_cycle_rd = mdv_read?1'b1:video_rd;
|
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
|
// video and CPU/data_io time share the sdram bus
|
||||||
wire [24:0] sdram_addr = video_cycle?video_cycle_addr:sys_addr;
|
wire [24:0] sdram_addr = video_cycle?video_cycle_addr:sys_addr;
|
||||||
@@ -352,7 +356,7 @@ osd #(12,0,5) osd (
|
|||||||
// -------------------------------------- reset ------------------------------------
|
// -------------------------------------- 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;
|
reg [11:0] reset_cnt;
|
||||||
wire reset = (reset_cnt != 0);
|
wire reset = (reset_cnt != 0);
|
||||||
always @(posedge clk2) begin
|
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 [1:0] zx8302_addr = {cpu_addr[5], cpu_addr[1]};
|
||||||
wire [15:0] zx8302_dout;
|
wire [15:0] zx8302_dout;
|
||||||
|
|
||||||
wire mdv_download = (dio_index == 1) && dio_download;
|
wire mdv_download = (dio_index == 1) && dio_download; //signal for active download from SD
|
||||||
wire mdv_men;
|
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 mdv_read;
|
||||||
|
wire mdv2_read;
|
||||||
wire [24:0] mdv_addr;
|
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;
|
wire audio;
|
||||||
assign AUDIO_L = audio;
|
assign AUDIO_L = audio;
|
||||||
@@ -397,7 +406,7 @@ zx8302 zx8302 (
|
|||||||
.cpu_addr ( zx8302_addr ),
|
.cpu_addr ( zx8302_addr ),
|
||||||
.cpu_ds ( cpu_ds ),
|
.cpu_ds ( cpu_ds ),
|
||||||
.cpu_din ( cpu_dout ),
|
.cpu_din ( cpu_dout ),
|
||||||
.cpu_dout ( zx8302_dout ),
|
.cpu_dout ( zx8302_dout ),
|
||||||
|
|
||||||
// joysticks
|
// joysticks
|
||||||
.js0 ( js0[4:0] ),
|
.js0 ( js0[4:0] ),
|
||||||
@@ -410,15 +419,22 @@ zx8302 zx8302 (
|
|||||||
|
|
||||||
// microdrive sdram interface
|
// microdrive sdram interface
|
||||||
.mdv_addr ( mdv_addr ),
|
.mdv_addr ( mdv_addr ),
|
||||||
|
.mdv2_addr ( mdv2_addr ),
|
||||||
.mdv_din ( sdram_dout ),
|
.mdv_din ( sdram_dout ),
|
||||||
.mdv_read ( mdv_read ),
|
.mdv_read ( mdv_read ),
|
||||||
|
.mdv2_read ( mdv2_read ),
|
||||||
.mdv_men ( mdv_men ),
|
.mdv_men ( mdv_men ),
|
||||||
.video_cycle ( video_cycle ),
|
.video_cycle ( video_cycle ),
|
||||||
|
|
||||||
.mdv_reverse ( status[2] ),
|
.mdv_reverse ( status[2] ),
|
||||||
|
|
||||||
.mdv_download ( mdv_download ),
|
.mdv_download ( mdv_download ),
|
||||||
|
.mdv2_download ( mdv2_download ),
|
||||||
|
|
||||||
|
.mdv_seldrive ( mdv_seldrive) ,
|
||||||
|
|
||||||
.mdv_dl_addr ( dio_addr )
|
.mdv_dl_addr ( dio_addr )
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -32,14 +32,19 @@ module zx8302 (
|
|||||||
|
|
||||||
// sdram interface for microdrive emulation
|
// sdram interface for microdrive emulation
|
||||||
output [24:0] mdv_addr,
|
output [24:0] mdv_addr,
|
||||||
|
output [24:0] mdv2_addr,
|
||||||
input [15:0] mdv_din,
|
input [15:0] mdv_din,
|
||||||
output mdv_read,
|
output mdv_read,
|
||||||
|
output mdv2_read,
|
||||||
input mdv_men,
|
input mdv_men,
|
||||||
input video_cycle,
|
input video_cycle,
|
||||||
|
|
||||||
// interface to watch MDV cartridge upload
|
// interface to watch MDV cartridge upload
|
||||||
input [24:0] mdv_dl_addr,
|
input [24:0] mdv_dl_addr,
|
||||||
input mdv_download,
|
input mdv_download,
|
||||||
|
input mdv2_download,
|
||||||
|
|
||||||
|
output mdv_seldrive,
|
||||||
|
|
||||||
input mdv_reverse,
|
input mdv_reverse,
|
||||||
output led,
|
output led,
|
||||||
@@ -127,8 +132,10 @@ end
|
|||||||
// bit 7 COMDATA
|
// bit 7 COMDATA
|
||||||
|
|
||||||
wire [7:0] io_status = { zx8302_comdata_in, ipc_busy, 2'b00,
|
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 =
|
assign cpu_dout =
|
||||||
// 18000/18001 and 18002/18003
|
// 18000/18001 and 18002/18003
|
||||||
(cpu_addr == 2'b00)?rtc[47:32]:
|
(cpu_addr == 2'b00)?rtc[47:32]:
|
||||||
@@ -136,7 +143,7 @@ assign cpu_dout =
|
|||||||
|
|
||||||
// 18020/18021 and 18022/18023
|
// 18020/18021 and 18022/18023
|
||||||
(cpu_addr == 2'b10)?{io_status, irq_pending}:
|
(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;
|
16'h0000;
|
||||||
|
|
||||||
@@ -213,7 +220,7 @@ always @(posedge vs or posedge vsync_irq_reset) begin
|
|||||||
end
|
end
|
||||||
|
|
||||||
// toggling the mask will also trigger irqs ...
|
// 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;
|
reg gap_irq;
|
||||||
wire gap_irq_reset = reset || irq_ack[0];
|
wire gap_irq_reset = reset || irq_ack[0];
|
||||||
always @(posedge gap_irq_in or posedge gap_irq_reset) begin
|
always @(posedge gap_irq_in or posedge gap_irq_reset) begin
|
||||||
@@ -236,16 +243,22 @@ end
|
|||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
wire mdv_gap;
|
wire mdv_gap;
|
||||||
|
wire mdv2_gap;
|
||||||
wire mdv_tx_empty;
|
wire mdv_tx_empty;
|
||||||
|
wire mdv2_tx_empty;
|
||||||
wire mdv_rx_ready;
|
wire mdv_rx_ready;
|
||||||
|
wire mdv2_rx_ready;
|
||||||
wire [7:0] mdv_byte;
|
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 (
|
mdv mdv (
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.reset ( init ),
|
.reset ( init ),
|
||||||
|
|
||||||
|
.mdv_drive (1), //This is MDV1_
|
||||||
|
|
||||||
.sel ( mdv_sel[0] ),
|
.sel ( mdv_sel[0] ),
|
||||||
|
|
||||||
.reverse ( mdv_reverse ),
|
.reverse ( mdv_reverse ),
|
||||||
@@ -268,12 +281,47 @@ mdv mdv (
|
|||||||
.mem_din ( mdv_din )
|
.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
|
// the microdrive control register mctrl generates the drive selection
|
||||||
|
// mdv_sel = 1 for mdv1_, mdv_sel = 2 for mdv2_
|
||||||
reg [7:0] mdv_sel;
|
reg [7:0] mdv_sel;
|
||||||
|
|
||||||
always @(negedge mctrl[1])
|
always @(negedge mctrl[1])
|
||||||
mdv_sel <= { mdv_sel[6:0], mctrl[0] };
|
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 --------------------------------------
|
// -------------------------------------- RTC --------------------------------------
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user