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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
|
||||
);
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
@@ -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 --------------------------------------
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user