update tsconf to commit 83afbba6f5d366f96297028aa3d64512fa254a51

This commit is contained in:
Eugene Lozovoy
2024-09-12 16:28:38 +03:00
parent ba7d903e12
commit 3681138b01
47 changed files with 5648 additions and 4341 deletions

61
rtl/common/clock.v Normal file
View File

@ -0,0 +1,61 @@
// This module receives 28 MHz as input clock
// and makes strobes for all clocked parts
// clk |<EFBFBD>__<EFBFBD><EFBFBD>__<EFBFBD><EFBFBD>__<EFBFBD><EFBFBD>__<EFBFBD>| period = 28 duty = 50% phase = 0
// cnt |< 0>< 1>< 2>< 3>|
// f0 |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>____<EFBFBD><EFBFBD><EFBFBD><EFBFBD>____| period = 14 duty = 50% phase = 0
// f1 |____<EFBFBD><EFBFBD><EFBFBD><EFBFBD>____<EFBFBD><EFBFBD><EFBFBD><EFBFBD>| period = 14 duty = 50% phase = 180
// h0 |<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>________| period = 7 duty = 50% phase = 0
// h1 |________<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>| period = 7 duty = 50% phase = 180
// c0 |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>____________| period = 7 duty = 25% phase = 0
// c1 |____<EFBFBD><EFBFBD><EFBFBD><EFBFBD>________| period = 7 duty = 25% phase = 90
// c2 |________<EFBFBD><EFBFBD><EFBFBD><EFBFBD>____| period = 7 duty = 25% phase = 180
// c3 |____________<EFBFBD><EFBFBD><EFBFBD><EFBFBD>| period = 7 duty = 25% phase = 270
`include "tune.v"
module clock
(
input wire clk,
input wire [1:0] ay_mod,
output wire f0, f1,
output wire h0, h1,
output wire c0, c1, c2, c3,
output wire ay_clk
);
reg [1:0] f = 'b01;
reg [1:0] h = 'b01;
reg [3:0] c = 'b0001;
always @(posedge clk)
begin
f <= ~f;
if (f[1]) h <= ~h;
c <= {c[2:0], c[3]};
end
assign f0 = f[0];
assign f1 = f[1];
assign h0 = h[0];
assign h1 = h[1];
assign c0 = c[0];
assign c1 = c[1];
assign c2 = c[2];
assign c3 = c[3];
// AY clock generator
// ay_mod - clock selection for AY, MHz: 00 - 1.75 / 01 - 1.7733 / 10 - 3.5 / 11 - 3.546
reg [7:0] skip_cnt = 0;
reg [3:0] ay_cnt = 0;
assign ay_clk = ay_mod[1] ? ay_cnt[2] : ay_cnt[3];
always @(posedge clk)
begin
skip_cnt <= skip_cnt[7] ? 8'd73 : skip_cnt - 8'd1;
ay_cnt <= ay_cnt + (skip_cnt[7] & ay_mod[0] ? 4'd2 : 4'd1);
end
endmodule

429
rtl/common/dma.v Normal file
View File

@ -0,0 +1,429 @@
// This module serves direct DRAM-to-device data transfer
`include "tune.v"
module dma
(
// clocks
input wire clk,
input wire c2,
input wire rst_n,
// interface
`ifdef FDR
input wire [9:0] dmaport_wr,
`else
input wire [8:0] dmaport_wr,
`endif
output wire dma_act,
output reg [15:0] data = 0,
output wire [ 7:0] wraddr,
output wire int_start,
// Z80
input wire [7:0] zdata,
// DRAM interface
output wire [20:0] dram_addr,
input wire [15:0] dram_rddata,
output wire [15:0] dram_wrdata,
output wire dram_req,
output wire dram_rnw,
input wire dram_next,
// SPI interface
input wire [7:0] spi_rddata,
output wire [7:0] spi_wrdata,
output wire spi_req,
input wire spi_stb,
// WTPORT interface
input wire [7:0] wtp_rddata,
// output wire [7:0] wtp_wrdata,
output wire wtp_req,
input wire wtp_stb,
// IDE interface
input wire [15:0] ide_in,
output wire [15:0] ide_out,
output wire ide_req,
output wire ide_rnw,
input wire ide_stb,
`ifdef FDR
// FDD interface
input wire [7:0] fdr_in,
output wire fdr_req,
input wire fdr_stb,
input wire fdr_stop,
`endif
// CRAM interface
output wire cram_we,
// SFILE interface
output wire sfile_we
);
// mode:
// 0 - device to RAM (read from device)
// 1 - RAM to device (write to device)
wire dma_saddrl = dmaport_wr[0];
wire dma_saddrh = dmaport_wr[1];
wire dma_saddrx = dmaport_wr[2];
wire dma_daddrl = dmaport_wr[3];
wire dma_daddrh = dmaport_wr[4];
wire dma_daddrx = dmaport_wr[5];
wire dma_len = dmaport_wr[6];
wire dma_launch = dmaport_wr[7];
wire dma_num = dmaport_wr[8];
`ifdef FDR
wire dma_numh = dmaport_wr[9];
`endif
// devices
localparam DEV_RAM = 3'b001;
localparam DEV_BLT1 = 4'b1001;
`ifdef XTR_FEAT
localparam DEV_BLT2 = 4'b0110;
`endif
localparam DEV_FIL = 4'b0100;
localparam DEV_SPI = 3'b010;
localparam DEV_IDE = 3'b011;
localparam DEV_CRM = 4'b1100;
localparam DEV_SFL = 4'b1101;
localparam DEV_FDD = 4'b0101;
localparam DEV_WTP = 4'b0111;
wire state_dev;
wire ide_int_stb;
wire byte_sw_stb;
wire spi_int_stb;
wire wtp_int_stb;
reg dma_salgn;
reg dma_dalgn;
reg dma_asz;
reg phase; // 0 - read / 1 - write
reg phase_blt; // 0 - source / 1 - destination
reg bsel; // 0 - lsb / 1 - msb
reg dma_opt;
reg [3:0] device;
wire [2:0] dev_bid = device[2:0]; // bidirectional
wire [3:0] dev_uni = device[3:0]; // unidirectional
wire dma_wnr = device[3]; // 0 - device to RAM / 1 - RAM to device
`ifdef XTR_FEAT
wire dv_ram = (dev_uni == DEV_RAM) || (dev_uni == DEV_BLT1) || (dev_uni == DEV_BLT2) || (dev_uni == DEV_FIL);
wire dv_blt = (dev_uni == DEV_BLT1) || (dev_uni == DEV_BLT2);
`else
wire dv_ram = (dev_uni == DEV_RAM) || (dev_uni == DEV_BLT1) || (dev_uni == DEV_FIL);
wire dv_blt = (dev_uni == DEV_BLT1);
`endif
wire dv_fil = (dev_uni == DEV_FIL);
wire dv_spi = (dev_bid == DEV_SPI);
wire dv_ide = (dev_bid == DEV_IDE);
wire dv_crm = (dev_uni == DEV_CRM);
wire dv_sfl = (dev_uni == DEV_SFL);
wire dv_wtp = (dev_uni == DEV_WTP);
`ifdef FDR
wire dv_fdd = (dev_uni == DEV_FDD);
`endif
wire dev_req = dma_act && state_dev;
wire dev_stb = cram_we || sfile_we || ide_int_stb || (byte_sw_stb && bsel && dma_act);
`ifdef FDR
assign byte_sw_stb = spi_int_stb || wtp_int_stb || fdr_int_stb;
`else
assign byte_sw_stb = spi_int_stb || wtp_int_stb;
`endif
// blitter
// Mode 1
wire [7:0] blt1_data10 = |data[7:0] ? data[7:0] : dram_rddata[7:0];
wire [7:0] blt1_data32 = |data[15:8] ? data[15:8] : dram_rddata[15:8];
wire [3:0] blt1_data0 = |data[3:0] ? data[3:0] : dram_rddata[3:0];
wire [3:0] blt1_data1 = |data[7:4] ? data[7:4] : dram_rddata[7:4];
wire [3:0] blt1_data2 = |data[11:8] ? data[11:8] : dram_rddata[11:8];
wire [3:0] blt1_data3 = |data[15:12] ? data[15:12] : dram_rddata[15:12];
wire [7:0] blt1_data_l = dma_asz ? blt1_data10 : {blt1_data1, blt1_data0};
wire [7:0] blt1_data_h = dma_asz ? blt1_data32 : {blt1_data3, blt1_data2};
wire [15:0] blt1_rddata = {blt1_data_h, blt1_data_l};
`ifdef XTR_FEAT
// Mode 2
localparam msk = 8'd255;
wire [8:0] sum80 = data[7:0] + dram_rddata[7:0];
wire [8:0] sum81 = data[15:8] + dram_rddata[15:8];
wire [4:0] sum40 = data[3:0] + dram_rddata[3:0];
wire [4:0] sum41 = data[7:4] + dram_rddata[7:4];
wire [4:0] sum42 = data[11:8] + dram_rddata[11:8];
wire [4:0] sum43 = data[15:12] + dram_rddata[15:12];
wire [7:0] blt2_8_data0 = ((sum80 > msk) && dma_opt) ? msk : sum80[7:0];
wire [7:0] blt2_8_data1 = ((sum81 > msk) && dma_opt) ? msk : sum81[7:0];
wire [3:0] blt2_4_data0 = ((sum40 > msk[3:0]) && dma_opt) ? msk[3:0] : sum40[3:0];
wire [3:0] blt2_4_data1 = ((sum41 > msk[3:0]) && dma_opt) ? msk[3:0] : sum41[3:0];
wire [3:0] blt2_4_data2 = ((sum42 > msk[3:0]) && dma_opt) ? msk[3:0] : sum42[3:0];
wire [3:0] blt2_4_data3 = ((sum43 > msk[3:0]) && dma_opt) ? msk[3:0] : sum43[3:0];
wire [7:0] blt2_data_0 = dma_asz ? blt2_8_data0 : {blt2_4_data1, blt2_4_data0};
wire [7:0] blt2_data_1 = dma_asz ? blt2_8_data1 : {blt2_4_data3, blt2_4_data2};
wire [15:0] blt2_rddata = {blt2_data_1, blt2_data_0};
wire [15:0] blt_rddata = (dev_uni == DEV_BLT1) ? blt1_rddata : blt2_rddata;
`else // XTR_FEAT
wire [15:0] blt_rddata = blt1_rddata;
`endif
// states
wire state_rd = ~phase;
wire state_wr = phase;
assign state_dev = !dv_ram && (dma_wnr ^ !phase);
wire state_mem = dv_ram || (dma_wnr ^ phase);
// states processing
wire blt_hook = dv_blt && !phase_blt && !phase;
wire phase_end_ram = state_mem && dram_next && !blt_hook;
wire phase_end_dev = state_dev && dev_stb;
wire phase_end = phase_end_ram || phase_end_dev;
wire fil_hook = dv_fil && phase;
wire phase_blt_end = state_mem && dram_next && !phase;
// blitter cycles:
// phase phase_blt blt_hook activity
// 0 0 1 read src
// 0 1 0 read dst
// 1 1 0 write dst
always @(posedge clk)
if (dma_launch) // write to DMACtrl - launch of DMA burst
begin
dma_opt <= zdata[6];
dma_salgn <= zdata[5];
dma_dalgn <= zdata[4];
dma_asz <= zdata[3];
device <= {zdata[7], zdata[2:0]};
phase <= 1'b0;
phase_blt <= 1'b0;
bsel <= 1'b0;
end
else
begin
if (phase_end && !fil_hook)
phase <= ~phase;
if (phase_blt_end)
phase_blt <= ~phase_blt;
if (byte_sw_stb)
bsel <= ~bsel;
end
// data aquiring
always @(posedge clk)
if (state_rd)
begin
if (dram_next)
data <= (dv_blt && phase_blt) ? blt_rddata : dram_rddata;
if (ide_int_stb)
data <= ide_in;
if (spi_int_stb)
begin
if (bsel)
data[15:8] <= spi_rddata;
else
data[7:0] <= spi_rddata;
end
if (wtp_int_stb)
begin
if (bsel)
data[15:8] <= wtp_rddata;
else
data[7:0] <= wtp_rddata;
end
`ifdef FDR
if (fdr_int_stb)
begin
if (bsel)
data[15:8] <= fdr_in;
else
data[7:0] <= fdr_in;
end
`endif
end
// counter processing
reg [7:0] b_len; // length of burst
reg [7:0] b_ctr; // counter for cycles in burst
wire [8:0] b_ctr_dec = {1'b0, b_ctr[7:0]} - 9'b1;
wire next_burst = b_ctr_dec[8];
wire [7:0] b_ctr_next = next_burst ? b_len : b_ctr_dec[7:0];
`ifdef FDR
reg [9:0] b_num; // number of bursts
reg [10:0] n_ctr; // counter for bursts
wire [10:0] n_ctr_dec = n_ctr - next_burst;
assign dma_act = !n_ctr[10];
`else
reg [7:0] b_num; // number of bursts
reg [8:0] n_ctr; // counter for bursts
wire [8:0] n_ctr_dec = n_ctr - next_burst;
assign dma_act = !n_ctr[8];
`endif
always @(posedge clk)
`ifdef FDR
if (!rst_n || (dv_fdd && fdr_stop))
n_ctr[10] <= 1'b1;
`else
if (!rst_n)
n_ctr[8] <= 1'b1;
`endif
else if (dma_launch)
begin
b_ctr <= b_len;
n_ctr <= {1'b0, b_num};
end
else if (phase && phase_end) // cycle processed
begin
b_ctr <= b_ctr_next;
n_ctr <= n_ctr_dec;
end
// loading of burst parameters
always @(posedge clk)
begin
if (dma_len)
b_len <= zdata;
if (dma_num)
`ifdef FDR
b_num[7:0] <= zdata;
if (dma_numh)
b_num[9:8] <= zdata[1:0];
`else
b_num <= zdata;
`endif
end
// address processing
// source
reg [20:0] s_addr; // current source address
reg [7:0] s_addr_r; // source lower address
wire [8:0] s_addr_inc_l = {1'b0, s_addr[7:0]} + 9'b1;
wire [1:0] s_addr_add_h = dma_salgn ? {next_burst && dma_asz, next_burst && !dma_asz} : {s_addr_inc_l[8], 1'b0};
wire [13:0] s_addr_next_h = s_addr[20:7] + s_addr_add_h;
wire [7:0] s_addr_next_l = (dma_salgn && next_burst) ? s_addr_r : s_addr_inc_l[7:0];
wire s_addr_next_m = dma_salgn ? (dma_asz ? s_addr_next_l[7] : s_addr_next_h[0]) : s_addr_inc_l[7];
wire [20:0] s_addr_next = {s_addr_next_h[13:1], s_addr_next_m, s_addr_next_l[6:0]};
always @(posedge clk)
if ((dram_next || dev_stb) && state_rd && (!dv_blt || !phase_blt)) // increment RAM source addr
s_addr <= s_addr_next;
else
begin
if (dma_saddrl)
begin
s_addr[6:0] <= zdata[7:1];
s_addr_r[6:0] <= zdata[7:1];
end
if (dma_saddrh)
begin
s_addr[12:7] <= zdata[5:0];
s_addr_r[7] <= zdata[0];
end
if (dma_saddrx)
s_addr[20:13] <= zdata;
end
// destination
reg [20:0] d_addr; // current dest address
reg [7:0] d_addr_r; // dest lower address
wire [8:0] d_addr_inc_l = {1'b0, d_addr[7:0]} + 9'b1;
wire [1:0] d_addr_add_h = dma_dalgn ? {next_burst && dma_asz, next_burst && !dma_asz} : {d_addr_inc_l[8], 1'b0};
wire [13:0] d_addr_next_h = d_addr[20:7] + d_addr_add_h;
wire [7:0] d_addr_next_l = (dma_dalgn && next_burst) ? d_addr_r : d_addr_inc_l[7:0];
wire d_addr_next_m = dma_dalgn ? (dma_asz ? d_addr_next_l[7] : d_addr_next_h[0]) : d_addr_inc_l[7];
wire [20:0] d_addr_next = {d_addr_next_h[13:1], d_addr_next_m, d_addr_next_l[6:0]};
always @(posedge clk)
if ((dram_next || dev_stb) && state_wr) // increment RAM dest addr
d_addr <= d_addr_next;
else
begin
if (dma_daddrl)
begin
d_addr[6:0] <= zdata[7:1];
d_addr_r[6:0] <= zdata[7:1];
end
if (dma_daddrh)
begin
d_addr[12:7] <= zdata[5:0];
d_addr_r[7] <= zdata[0];
end
if (dma_daddrx)
d_addr[20:13] <= zdata;
end
// INT generation
reg dma_act_r = 0;
always @(posedge clk)
dma_act_r <= dma_act && rst_n;
assign int_start = !dma_act && dma_act_r;
assign wraddr = d_addr[7:0];
// DRAM
assign dram_addr = state_rd ? ((!dv_blt || !phase_blt) ? s_addr : d_addr) : d_addr;
assign dram_wrdata = data;
assign dram_req = dma_act && state_mem;
assign dram_rnw = state_rd;
assign cram_we = dev_req && dv_crm && state_wr;
assign sfile_we = dev_req && dv_sfl && state_wr;
`ifdef FDR
// FDD
wire fdr_int_stb = dv_fdd && fdr_stb;
assign fdr_req = dev_req && dv_fdd;
`endif
// SPI
assign spi_int_stb = dv_spi && spi_stb;
assign spi_wrdata = {8{state_rd}} | (bsel ? data[15:8] : data[7:0]); // send FF on read cycles
assign spi_req = dev_req && dv_spi;
// WTPORT
assign wtp_int_stb = dv_wtp && wtp_stb;
assign wtp_req = dev_req && dv_wtp;
// IDE
assign ide_int_stb = dv_ide && ide_stb;
assign ide_out = data;
assign ide_req = dev_req && dv_ide;
assign ide_rnw = state_rd;
endmodule

15
rtl/common/resetter.v Normal file
View File

@ -0,0 +1,15 @@
`include "tune.v"
// Reset from MCU must be long enough
module resetter
(
input wire clk,
input wire rst_in_n, // external asynchronous reset
output reg rst_out_n // synchronized reset
);
always @(posedge clk)
rst_out_n <= rst_in_n;
endmodule

74
rtl/common/spi.v Normal file
View File

@ -0,0 +1,74 @@
`include "tune.v"
module spi
(
// SPI wires
input wire clk, // system clock
output wire sck, // SCK
output reg sdo, // MOSI
input wire sdi, // MISO
input wire mode, // 0 - CPHA=0, CPOL=0 / 1 - CPHA=1, CPOL=0
// DMA interface
input wire dma_req,
input wire [7:0] dma_din,
// Z80 interface
input wire cpu_req,
input wire [7:0] cpu_din,
// output
output wire start, // start strobe, 1 clock length
output reg [7:0] dout
);
reg [4:0] counter = 5'b10000;
reg [7:0] shift = 0;
reg busy_r;
wire busy = !counter[4];
wire req = cpu_req || dma_req;
assign sck = counter[0];
assign start = req && !busy;
wire [7:0] din = dma_req ? dma_din : cpu_din;
wire cpha = mode;
always @(posedge clk)
begin
busy_r <= busy;
if (start)
begin
counter <= 5'b0;
sdo <= din[7];
shift[7:1] <= din[6:0];
end
else
begin
if (!counter[4])
counter <= counter + 5'd1;
if (cpha ? busy_r : busy)
begin
// shift in
if (cpha ? sck : !sck)
begin
shift[0] <= sdi;
if (&counter[3:1])
dout <= {shift[7:1], sdi};
end
// shift out
if (cpha ? !sck : sck)
begin
sdo <= shift[7];
shift[7:1] <= shift[6:0]; // last bit remains after end of exchange
end
end
end
end
endmodule

View File

@ -1,106 +0,0 @@
// PentEvo project (c) NedoPC 2008-2011
//
// Z80 clocking module, also contains some wait-stating when 14MHz
//
// IDEAL:
// clk _/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\
// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
// zclk /```\___/```\___/```\___/```````\_______/```````\_______/```````````````\_______________/```````````````\_______________/`
// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
// zpos `\___/```\___/```\___/```\___________/```\___________/```\___________________________/```\___________________________/```\
// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
// zneg _/```\___/```\___/```\_______/```\___________/```\___________________/```\___________________________/```\________________
// clock phasing:
// c3 must be zpos for 7mhz, therefore c1 - zneg
// for 3.5 mhz, c3 is both zpos and zneg (alternating)
// 14MHz rulez:
// 1. do variable stalls for memory access.
// 2. do fallback on 7mhz for external IO accesses
// 3. clock switch 14-7-3.5 only at RFSH
module zclock
(
input clk,
output zclk_out,
input c0, c2, f0, f1,
input iorq_s,
input external_port,
output reg zpos,
output reg zneg,
// stall enables and triggers
input cpu_stall,
input ide_stall,
input dos_on,
input vdos_off,
input [1:0] turbo // 2'b00 - 3.5 MHz
// 2'b01 - 7.0 MHz
// 2'b1x - 14.0 MHz
);
assign zclk_out = ~zclk_o;
reg zclk_o;
wire [1:0] turbo_int = turbo;
// wait generator
wire dos_io_stall = stall_start || !stall_count_end;
wire stall_start = dos_stall || io_stall;
wire dos_stall = dos_on || vdos_off;
wire io_stall = iorq_s && external_port && turbo_int[1];
wire stall_count_end = stall_count[3];
reg [3:0] stall_count;
always @(posedge clk) begin
if (stall_start) begin
if (dos_stall) stall_count <= 4; // 4 tacts 28MHz (1 tact 7MHz)
else if (io_stall) stall_count <= 0; // 8 tacts 28MHz (1 tact 3.5MHz)
end
else if (!stall_count_end) stall_count <= stall_count + 3'd1;
end
// Z80 clocking pre-strobes
wire pre_zpos = turbo_int[1] ? pre_zpos_140 : (turbo_int[0] ? pre_zpos_70 : pre_zpos_35);
wire pre_zneg = turbo_int[1] ? pre_zneg_140 : (turbo_int[0] ? pre_zneg_70 : pre_zneg_35);
wire pre_zpos_140 = f1;
wire pre_zneg_140 = f0;
wire pre_zpos_70 = c2;
wire pre_zneg_70 = c0;
wire pre_zpos_35 = c2_cnt && c2;
wire pre_zneg_35 = !c2_cnt && c2;
reg c2_cnt;
always @(posedge clk) if (c2) c2_cnt <= ~c2_cnt;
// Z80 clocking strobes
wire stall = cpu_stall || dos_io_stall || ide_stall;
always @(posedge clk) begin
zpos <= !stall && pre_zpos && zclk_o;
zneg <= !stall && pre_zneg && !zclk_o;
end
// make Z80 clock: account for external inversion and make some leading of clock
// 9.5 ns propagation delay: from clk posedge to zclk returned back any edge
// (1/28)/2=17.9ns half a clock lead
// 2.6ns lag because of non-output register emitting of zclk_o
// total: 5.8 ns lead of any edge of zclk relative to posedge of clk => ACCOUNT FOR THIS WHEN DOING INTER-CLOCK DATA TRANSFERS
// Z80 clocking
always @(negedge clk) begin
if (zpos) zclk_o <= 0;
if (zneg) zclk_o <= 1;
end
endmodule

View File

@ -1,71 +0,0 @@
module zint
(
input wire clk,
input wire zpos,
input wire res,
input wire int_start_frm,
input wire int_start_lin,
input wire int_start_dma,
input wire vdos,
input wire intack,
input wire [7:0] intmask,
output reg [7:0] im2vect,
output wire int_n
);
// In VDOS INTs are focibly disabled.
// For Frame, Line INT its generation is blocked, it will be lost.
// For DMA INT only its output is blocked, so DMA ISR will will be processed as soon as returned from VDOS.
assign int_n = ~(int_frm || int_lin || int_dma) | vdos;
wire dis_int_frm = !intmask[0];
wire dis_int_lin = !intmask[1];
wire dis_int_dma = !intmask[2];
wire intack_s = intack && !intack_r;
reg intack_r;
always @(posedge clk) intack_r <= intack;
reg [1:0] int_sel;
always @(posedge clk) begin
if (intack_s) begin
if (int_frm) im2vect <= 8'hFF; // priority 0
else if (int_lin) im2vect <= 8'hFD; // priority 1
else if (int_dma) im2vect <= 8'hFB; // priority 2
end
end
// ~INT generating
reg int_frm;
always @(posedge clk) begin
if (res || dis_int_frm) int_frm <= 0;
else if (int_start_frm) int_frm <= 1;
else if (intack_s || intctr_fin) int_frm <= 0; // priority 0
end
reg int_lin;
always @(posedge clk) begin
if (res || dis_int_lin) int_lin <= 0;
else if (int_start_lin) int_lin <= 1;
else if (intack_s && !int_frm) int_lin <= 0; // priority 1
end
reg int_dma;
always @(posedge clk) begin
if (res || dis_int_dma) int_dma <= 0;
else if (int_start_dma) int_dma <= 1;
else if (intack_s && !int_frm && !int_lin) int_dma <= 0; // priority 2
end
// ~INT counter
reg [5:0] intctr;
wire intctr_fin = intctr[5]; // 32 clks
always @(posedge clk, posedge int_start_frm) begin
if (int_start_frm) intctr <= 0;
else if (zpos && !intctr_fin && !vdos) intctr <= intctr + 1'b1;
end
endmodule

View File

@ -1,56 +0,0 @@
// This module maps z80 memory accesses into FPGA RAM and ports
module zmaps
(
// Z80 controls
input wire clk,
input wire memwr_s,
input wire [15:0] a,
input wire [7:0] d,
// config data
input wire [4:0] fmaddr,
// FPRAM data
output wire [15:0] zmd,
output wire [7:0] zma,
// DMA
input wire [15:0] dma_data,
input wire [7:0] dma_wraddr,
input wire dma_cram_we,
input wire dma_sfile_we,
// write strobes
output wire cram_we,
output wire sfile_we,
output wire regs_we
);
// addresses of files withing zmaps
localparam CRAM = 3'b000;
localparam SFYS = 3'b001;
localparam REGS = 4'b0100;
// control signals
wire hit = (a[15:12] == fmaddr[3:0]) && fmaddr[4] && memwr_s;
// write enables
assign cram_we = dma_req ? dma_cram_we : (a[11:9] == CRAM) && a[0] && hit;
assign sfile_we = dma_req ? dma_sfile_we : (a[11:9] == SFYS) && a[0] && hit;
assign regs_we = (a[11:8] == REGS) && hit;
// LSB fetching
assign zma = dma_req ? dma_wraddr : a[8:1];
assign zmd = dma_req ? dma_data : {d, zmd0};
reg [7:0] zmd0;
always @(posedge clk) if (!a[0] && hit) zmd0 <= d;
// DMA
wire dma_req = dma_cram_we || dma_sfile_we;
endmodule

View File

@ -1,228 +0,0 @@
// PentEvo project (c) NedoPC 2008-2009
//
// Z80 memory manager: routes ROM/RAM accesses, makes wait-states for 14MHz or stall condition, etc.
//
//
// clk _/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\
// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
// zclk /```\___/```\___/```\___/```````\_______/```````\_______/```````````````\_______________/```````````````\_______________/`
// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
// zpos `\___/```\___/```\___/```\___________/```\___________/```\___________________________/```\___________________________/```\
// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
// zneg _/```\___/```\___/```\_______/```\___________/```\___________________/```\___________________________/```\________________
module zmem
(
input clk,
input c0, c1, c2, c3,
input zneg, // strobes which show positive and negative edges of zclk
input zpos,
// Z80
input rst,
input [15:0] za,
output [ 7:0] zd_out, // output to Z80 bus
output zd_ena, // output to Z80 bus enable
input opfetch,
input opfetch_s,
input mreq,
input memrd,
input memwr,
input memwr_s,
input [ 1:0] turbo, // 2'b00 - 3.5,
// 2'b01 - 7.0,
// 2'b1x - 14.0
input [3:0] cache_en,
input [3:0] memconf,
input [31:0] xt_page,
output [4:0] rompg,
output csrom,
output romoe_n,
output romwe_n,
output dos,
output dos_on,
output dos_off,
output vdos,
output reg pre_vdos,
input vdos_on,
input vdos_off,
// DRAM
output cpu_req,
output [20:0] cpu_addr,
output cpu_wrbsel,
input [15:0] cpu_rddata,
input cpu_next,
input cpu_strobe,
input cpu_latch,
output cpu_stall // for zclock
);
// controls
wire rom128 = memconf[0];
wire w0_we = memconf[1];
wire w0_map_n = memconf[2];
wire w0_ram = memconf[3];
// pager
wire [1:0] win = za[15:14];
wire win0 = ~|win;
wire ramwr_en = !win0 || w0_we || vdos;
wire rom_n_ram = win0 && !w0_ram && !vdos;
wire [7:0] page = xtpage[win];
wire [7:0] xtpage[0:3];
assign xtpage[0] = vdos ? 8'hFF : {xt_page[7:2], w0_map_n ? xt_page[1:0] : {~dos, rom128}};
assign xtpage[1] = xt_page[15:8];
assign xtpage[2] = xt_page[23:16];
assign xtpage[3] = xt_page[31:24];
// ROM chip
assign csrom = rom_n_ram;
assign romoe_n = !memrd;
assign romwe_n = !(memwr && w0_we);
assign rompg = xtpage[0][4:0];
// RAM
assign zd_ena = memrd;
wire ramreq = ((memrd && !cache_hit_en) || (memwr && ramwr_en));
// DOS signal control
assign dos_on = win0 && opfetch_s && (za[13:8]==6'h3D) && rom128 && !w0_map_n;
assign dos_off = !win0 && opfetch_s && !vdos;
assign dos = (dos_on || dos_off) ^^ dos_r; // to make dos appear 1 clock earlier than dos_r
reg dos_r;
always @(posedge clk) begin
if (rst) dos_r <= 0;
else if (dos_off) dos_r <= 0;
else if (dos_on) dos_r <= 1;
end
// VDOS signal control
// vdos turn on/off is delayed till next opfetch due to INIR that writes right after iord cycle
assign vdos = opfetch ? pre_vdos : vdos_r; // vdos appears as soon as first opfetch
reg vdos_r;
always @(posedge clk) begin
if (rst || vdos_off) begin
pre_vdos <= 0;
vdos_r <= 0;
end
else if (vdos_on) pre_vdos <= 1;
else if (opfetch_s) vdos_r <= pre_vdos;
end
// address, data in and data out
assign cpu_wrbsel = za[0];
assign cpu_addr[20:0] = {page, za[13:1]};
wire [15:0] mem_d = cpu_latch ? cpu_rddata : cache_d;
assign zd_out = ~cpu_wrbsel ? mem_d[7:0] : mem_d[15:8];
// Z80 controls
assign cpu_req = turbo14 ? cpureq_14 : cpureq_357;
assign cpu_stall = turbo14 ? stall14 : stall357;
wire turbo14 = turbo[1];
// 7/3.5MHz support
wire cpureq_357 = ramreq && !ramreq_r;
wire stall357 = cpureq_357 && !cpu_next;
reg ramreq_r;
always @(posedge clk) if (c3 && !cpu_stall) ramreq_r <= ramreq;
// 14MHz support
// wait tables:
//
// M1 opcode fetch, dram_beg concurs with:
// c3: +3
// c2: +4
// c1: +5
// c0: +6
//
// memory read, dram_beg concurs with:
// c3: +2
// c2: +3
// c1: +4
// c0: +5
//
// memory write: no wait
//
// special case: if dram_beg pulses 1 when cpu_next is 0,
// unconditional wait has to be performed until cpu_next is 1, and
// then wait as if dram_beg would concur with c0
// memrd, opfetch - wait till c3 && cpu_next,
// memwr - wait till cpu_next
wire cpureq_14 = dram_beg || pending_cpu_req;
wire stall14 = stall14_ini || stall14_cyc || stall14_fin;
wire dram_beg = ramreq && !pre_ramreq_r && zneg;
reg pre_ramreq_r;
always @(posedge clk) if (zneg) pre_ramreq_r <= ramreq;
reg pending_cpu_req;
always @(posedge clk) begin
if (rst) pending_cpu_req <= 0;
else if (cpu_next && c3) pending_cpu_req <= 0;
else if (dram_beg) pending_cpu_req <= 1;
end
wire stall14_ini = dram_beg && (!cpu_next || opfetch || memrd); // no wait at all in write cycles, if next dram cycle is available
wire stall14_cyc = memrd ? stall14_cycrd : !cpu_next;
reg stall14_cycrd;
always @(posedge clk) begin
if (rst) stall14_cycrd <= 0;
else if (cpu_next && c3) stall14_cycrd <= 0;
else if (dram_beg && (!c3 || !cpu_next) && (opfetch || memrd)) stall14_cycrd <= 1;
end
reg stall14_fin;
always @(posedge clk) begin
if (rst) stall14_fin <= 0;
else if (stall14_fin && ((opfetch && c1) || (memrd && c2))) stall14_fin <= 0;
else if (cpu_next && c3 && cpu_req && (opfetch || memrd)) stall14_fin <= 1;
end
// cache
// wire cache_hit = (ch_addr[7:2] != 6'b011100) && (cpu_hi_addr == cache_a) && cache_v; // debug for BM
wire cache_hit = (cpu_hi_addr == cache_a) && cache_v; // asynchronous signal meaning that address requested by CPU is cached and valid
wire cache_hit_en = cache_hit && cache_en[win];
wire cache_inv = cache_hit && memwr_s && ramwr_en; // cache invalidation should be only performed if write happens to cached address
wire [12:0] cpu_hi_addr = {page[7:0], za[13:9]};
wire [12:0] cache_a;
wire [7:0] ch_addr = cpu_addr[7:0];
wire [15:0] cache_d;
wire cache_v;
dpram #(.DATAWIDTH(16), .ADDRWIDTH(8)) cache_data
(
.clock(clk),
.address_a(ch_addr),
.data_a(cpu_rddata),
.wren_a(cpu_strobe),
.address_b(ch_addr),
.q_b(cache_d)
);
dpram #(.DATAWIDTH(14), .ADDRWIDTH(8)) cache_addr
(
.clock(clk),
.address_a(ch_addr),
.data_a({!cache_inv, cpu_hi_addr}),
.wren_a(cpu_strobe || cache_inv),
.address_b(ch_addr),
.q_b({cache_v, cache_a})
);
endmodule

View File

@ -1,469 +0,0 @@
// PentEvo project (c) NedoPC 2008-2010
module zports
(
input clk,
input [7:0] din,
output reg [7:0] dout,
output dataout,
input [15:0] a,
input rst, // system reset
input opfetch,
input rd,
input wr,
input rdwr,
input iorq,
input iorq_s,
input iord,
input iord_s,
input iowr,
input iowr_s,
input iordwr,
input iordwr_s,
output porthit, // when internal port hit occurs, this is 1, else 0; used for iorq1_n iorq2_n on zxbus
output external_port, // asserts for AY and VG93 accesses
output zborder_wr,
output border_wr,
output zvpage_wr,
output vpage_wr,
output vconf_wr,
output gx_offsl_wr,
output gx_offsh_wr,
output gy_offsl_wr,
output gy_offsh_wr,
output t0x_offsl_wr,
output t0x_offsh_wr,
output t0y_offsl_wr,
output t0y_offsh_wr,
output t1x_offsl_wr,
output t1x_offsh_wr,
output t1y_offsl_wr,
output t1y_offsh_wr,
output tsconf_wr,
output palsel_wr,
output tmpage_wr,
output t0gpage_wr,
output t1gpage_wr,
output sgpage_wr,
output hint_beg_wr ,
output vint_begl_wr,
output vint_begh_wr,
output [31:0] xt_page,
output reg [4:0] fmaddr,
input regs_we,
output reg [7:0] sysconf,
output reg [7:0] memconf,
output reg [3:0] cacheconf,
output reg [7:0] fddvirt,
output [8:0] dmaport_wr,
input dma_act,
output reg [1:0] dmawpdev,
output reg [7:0] intmask,
input dos,
input vdos,
output vdos_on,
output vdos_off,
output ay_bdir,
output ay_bc1,
output covox_wr,
output beeper_wr,
input tape_read,
input [4:0] keys_in, // keys (port FE)
input [7:0] mus_in, // mouse (xxDF)
input [5:0] kj_in,
input vg_intrq,
input vg_drq, // from vg93 module - drq + irq read
output vg_cs_n,
output vg_wrFF,
output [1:0] drive_sel, // disk drive selection
// SPI
output sdcs_n,
output sd_start,
output [7:0] sd_datain,
input [7:0] sd_dataout,
// WAIT-ports related
output reg [7:0] wait_addr,
output wait_start_gluclock, // begin wait from some ports
output wait_start_comport, //
output reg [7:0] wait_write,
input [7:0] wait_read
);
assign sdcs_n = spi_cs_n[0];
localparam FDR_VER = 1'b0;
localparam VDAC_VER = 3'h3;
localparam PORTFE = 8'hFE;
localparam PORTFD = 8'hFD;
localparam PORTXT = 8'hAF;
localparam PORTF7 = 8'hF7;
localparam COVOX = 8'hFB;
localparam VGCOM = 8'h1F;
localparam VGTRK = 8'h3F;
localparam VGSEC = 8'h5F;
localparam VGDAT = 8'h7F;
localparam VGSYS = 8'hFF;
localparam KJOY = 8'h1F;
localparam KMOUSE = 8'hDF;
localparam SDCFG = 8'h77;
localparam SDDAT = 8'h57;
localparam COMPORT = 8'hEF; // F8EF..FFEF - rs232 ports
wire [7:0] loa = a[7:0];
wire [7:0] hoa = regs_we ? a[7:0] : a[15:8];
assign porthit = ((loa==PORTFE) || (loa==PORTXT) || (loa==PORTFD) || (loa==COVOX))
|| ((loa==PORTF7) && !dos)
|| ((vg_port || vgsys_port) && (dos || open_vg))
|| ((loa==KJOY) && !dos && !open_vg)
|| (loa==KMOUSE)
|| (((loa==SDCFG) || (loa==SDDAT)) && (!dos || vdos))
|| (loa==COMPORT);
wire vg_port = (loa==VGCOM) || (loa==VGTRK) || (loa==VGSEC) || (loa==VGDAT);
wire vgsys_port = (loa==VGSYS);
assign external_port = ((loa==PORTFD) && a[15]) // AY
|| (((loa==VGCOM) || (loa==VGTRK) || (loa==VGSEC) || (loa==VGDAT)) && (dos || open_vg));
assign dataout = porthit && iord && (~external_port);
reg iowr_reg;
reg iord_reg;
reg port_wr;
reg port_rd;
always @(posedge clk) begin
iowr_reg <= iowr;
port_wr <= (!iowr_reg && iowr);
iord_reg <= iord;
port_rd <= (!iord_reg && iord);
end
// reading ports
always @(*) begin
case (loa)
PORTFE:
dout = {1'b1, tape_read, 1'b0, keys_in};
PORTXT:
begin
case (hoa)
XSTAT:
dout = {1'b0, pwr_up_reg, FDR_VER, 2'b0, VDAC_VER};
DMASTAT:
dout = {dma_act, 7'b0};
RAMPAGE + 8'd2, RAMPAGE + 8'd3:
dout = rampage[hoa[1:0]];
default:
dout = 8'hFF;
endcase
end
VGSYS:
dout = {vg_intrq, vg_drq, 6'b111111};
KJOY:
dout = {2'b00, kj_in};
KMOUSE:
dout = mus_in;
SDCFG:
dout = 8'h00; // always SD inserted, SD is in R/W mode
SDDAT:
dout = sd_dataout;
PORTF7:
begin
if (!a[14] && (a[8] ^ dos) && gluclock_on) dout = wait_read; // $BFF7 - data i/o
else dout = 8'hFF; // any other $xxF7 port
end
COMPORT:
dout = wait_read; // $F8EF..$FFEF
default:
dout = 8'hFF;
endcase
end
// power-up
// This bit is loaded as 1 while FPGA is configured
// and automatically reset to 0 after STATUS port reading
reg pwr_up_reg;
reg pwr_up = 1;
always @(posedge clk) begin
if (iord_s & (loa == PORTXT) & (hoa == XSTAT)) begin
pwr_up_reg <= pwr_up;
pwr_up <= 1'b0;
end
end
// writing ports
//#nnAF
localparam VCONF = 8'h00;
localparam VPAGE = 8'h01;
localparam GXOFFSL = 8'h02;
localparam GXOFFSH = 8'h03;
localparam GYOFFSL = 8'h04;
localparam GYOFFSH = 8'h05;
localparam TSCONF = 8'h06;
localparam PALSEL = 8'h07;
localparam XBORDER = 8'h0F;
localparam T0XOFFSL = 8'h40;
localparam T0XOFFSH = 8'h41;
localparam T0YOFFSL = 8'h42;
localparam T0YOFFSH = 8'h43;
localparam T1XOFFSL = 8'h44;
localparam T1XOFFSH = 8'h45;
localparam T1YOFFSL = 8'h46;
localparam T1YOFFSH = 8'h47;
localparam RAMPAGE = 8'h10; // this covers #10-#13
localparam FMADDR = 8'h15;
localparam TMPAGE = 8'h16;
localparam T0GPAGE = 8'h17;
localparam T1GPAGE = 8'h18;
localparam SGPAGE = 8'h19;
localparam DMASADDRL = 8'h1A;
localparam DMASADDRH = 8'h1B;
localparam DMASADDRX = 8'h1C;
localparam DMADADDRL = 8'h1D;
localparam DMADADDRH = 8'h1E;
localparam DMADADDRX = 8'h1F;
localparam SYSCONF = 8'h20;
localparam MEMCONF = 8'h21;
localparam HSINT = 8'h22;
localparam VSINTL = 8'h23;
localparam VSINTH = 8'h24;
localparam DMAWPD = 8'h25;
localparam DMALEN = 8'h26;
localparam DMACTRL = 8'h27;
localparam DMANUM = 8'h28;
localparam FDDVIRT = 8'h29;
localparam INTMASK = 8'h2A;
localparam CACHECONF = 8'h2B;
localparam DMAWPA = 8'h2D;
localparam XSTAT = 8'h00;
localparam DMASTAT = 8'h27;
assign dmaport_wr[0] = portxt_wr && (hoa == DMASADDRL);
assign dmaport_wr[1] = portxt_wr && (hoa == DMASADDRH);
assign dmaport_wr[2] = portxt_wr && (hoa == DMASADDRX);
assign dmaport_wr[3] = portxt_wr && (hoa == DMADADDRL);
assign dmaport_wr[4] = portxt_wr && (hoa == DMADADDRH);
assign dmaport_wr[5] = portxt_wr && (hoa == DMADADDRX);
assign dmaport_wr[6] = portxt_wr && (hoa == DMALEN);
assign dmaport_wr[7] = portxt_wr && (hoa == DMACTRL);
assign dmaport_wr[8] = portxt_wr && (hoa == DMANUM);
assign zborder_wr = portfe_wr;
assign border_wr = (portxt_wr && (hoa == XBORDER));
assign zvpage_wr = p7ffd_wr;
assign vpage_wr = (portxt_wr && (hoa == VPAGE ));
assign vconf_wr = (portxt_wr && (hoa == VCONF ));
assign gx_offsl_wr = (portxt_wr && (hoa == GXOFFSL));
assign gx_offsh_wr = (portxt_wr && (hoa == GXOFFSH));
assign gy_offsl_wr = (portxt_wr && (hoa == GYOFFSL));
assign gy_offsh_wr = (portxt_wr && (hoa == GYOFFSH));
assign t0x_offsl_wr = (portxt_wr && (hoa == T0XOFFSL));
assign t0x_offsh_wr = (portxt_wr && (hoa == T0XOFFSH));
assign t0y_offsl_wr = (portxt_wr && (hoa == T0YOFFSL));
assign t0y_offsh_wr = (portxt_wr && (hoa == T0YOFFSH));
assign t1x_offsl_wr = (portxt_wr && (hoa == T1XOFFSL));
assign t1x_offsh_wr = (portxt_wr && (hoa == T1XOFFSH));
assign t1y_offsl_wr = (portxt_wr && (hoa == T1YOFFSL));
assign t1y_offsh_wr = (portxt_wr && (hoa == T1YOFFSH));
assign tsconf_wr = (portxt_wr && (hoa == TSCONF));
assign palsel_wr = (portxt_wr && (hoa == PALSEL));
assign tmpage_wr = (portxt_wr && (hoa == TMPAGE));
assign t0gpage_wr = (portxt_wr && (hoa == T0GPAGE));
assign t1gpage_wr = (portxt_wr && (hoa == T1GPAGE));
assign sgpage_wr = (portxt_wr && (hoa == SGPAGE));
assign hint_beg_wr = (portxt_wr && (hoa == HSINT ));
assign vint_begl_wr = (portxt_wr && (hoa == VSINTL));
assign vint_begh_wr = (portxt_wr && (hoa == VSINTH));
assign beeper_wr = portfe_wr;
wire portfe_wr = (loa==PORTFE) && iowr_s;
assign covox_wr = (loa==COVOX) && iowr_s;
wire portxt_wr = ((loa==PORTXT) && iowr_s) || regs_we;
reg [7:0] rampage[0:3];
assign xt_page = {rampage[3], rampage[2], rampage[1], rampage[0]};
wire lock128 = lock128_3 ? 1'b0 : (lock128_2 ? m1_lock128 : memconf[6]);
wire lock128_2 = memconf[7:6] == 2'b10; // mode 2
wire lock128_3 = memconf[7:6] == 2'b11; // mode 3
reg m1_lock128;
always @(posedge clk) if (opfetch) m1_lock128 <= !(din[7] ^ din[6]);
always @(posedge clk) begin
if (rst) begin
fmaddr[4] <= 1'b0;
intmask <= 8'b1;
fddvirt <= 8'b0;
sysconf <= 8'h00; // 3.5 MHz
memconf <= 8'h04; // no map
cacheconf <= 4'h0; // no cache
rampage[0]<= 8'h00;
rampage[1]<= 8'h05;
rampage[2]<= 8'h02;
rampage[3]<= 8'h00;
end
else if (p7ffd_wr) begin
memconf[0] <= din[4];
rampage[3] <= {2'b0, lock128_3 ? {din[5], din[7:6]} : ({1'b0, lock128 ? 2'b0 : din[7:6]}), din[2:0]};
end
else if (portxt_wr) begin
if (hoa[7:2] == RAMPAGE[7:2]) rampage[hoa[1:0]] <= din;
if (hoa == FMADDR) fmaddr <= din[4:0];
if (hoa == SYSCONF) begin
sysconf <= din;
cacheconf <= {4{din[2]}};
end
if (hoa == DMAWPD) dmawpdev <= din[1:0];
if (hoa == CACHECONF) cacheconf <= din[3:0];
if (hoa == MEMCONF) memconf <= din;
if (hoa == FDDVIRT) fddvirt <= din;
if (hoa == INTMASK) intmask <= din;
end
end
// 7FFD port
wire p7ffd_wr = !a[15] && (loa==PORTFD) && iowr_s && !lock48;
reg lock48;
always @(posedge clk) begin
if (rst) lock48 <= 1'b0;
else if (p7ffd_wr && !lock128_3) lock48 <= din[5];
end
// AY control
wire ay_hit = (loa==PORTFD) & a[15];
assign ay_bc1 = ay_hit & a[14] & iordwr;
assign ay_bdir = ay_hit & iowr;
// VG93
wire [3:0] fddvrt = fddvirt[3:0];
wire virt_vg = fddvrt[drive_sel_raw];
wire open_vg = fddvirt[7];
assign drive_sel = {drive_sel_raw[1], drive_sel_raw[0]};
wire vg_wen = (dos || open_vg) && !vdos && !virt_vg;
assign vg_cs_n = !(iordwr && vg_port && vg_wen);
assign vg_wrFF = iowr_s && vgsys_port && vg_wen;
wire vg_wrDS = iowr_s && vgsys_port && (dos || open_vg);
assign vdos_on = iordwr_s && (vg_port || vgsys_port) && dos && !vdos && virt_vg;
assign vdos_off = iordwr_s && vg_port && vdos;
// write drive number
reg [1:0] drive_sel_raw;
always @(posedge clk) if (vg_wrDS) drive_sel_raw <= din[1:0];
// SD card (Z-controller compatible)
wire sdcfg_wr;
wire sddat_wr;
wire sddat_rd;
reg [1:0] spi_cs_n;
assign sdcfg_wr = ((loa==SDCFG) && iowr_s && (!dos || vdos));
assign sddat_wr = ((loa==SDDAT) && iowr_s && (!dos || vdos));
assign sddat_rd = ((loa==SDDAT) && iord_s);
// SDCFG write - sdcs_n control
always @(posedge clk) begin
if (rst) spi_cs_n <= 2'b11;
else if (sdcfg_wr) spi_cs_n <= {~din[2], din[1]};
end
// start signal for SPI module with resyncing to fclk
assign sd_start = sddat_wr || sddat_rd;
// data for SPI module
assign sd_datain = wr ? din : 8'hFF;
// xxF7
wire portf7_wr = ((loa==PORTF7) && (a[8]==1'b1) && port_wr && (!dos || vdos));
wire portf7_rd = ((loa==PORTF7) && (a[8]==1'b1) && port_rd && (!dos || vdos));
// EFF7 port
reg [7:0] peff7;
always @(posedge clk) begin
if (rst) peff7 <= 8'h00;
else if (!a[12] && portf7_wr && !dos) peff7 <= din; // #EEF7 in dos is not accessible
end
// gluclock ports
wire gluclock_on = peff7[7] || dos; // in dos mode EEF7 is not accessible, gluclock access is ON in dos mode.
// comports
wire comport_wr = ((loa == COMPORT) && port_wr);
wire comport_rd = ((loa == COMPORT) && port_rd);
// write to wait registers
always @(posedge clk) begin
// gluclocks
if (gluclock_on && portf7_wr) begin
if (!a[14]) wait_write <= din; // $BFF7 - data reg
if (!a[13]) wait_addr <= din; // $DFF7 - addr reg
end
// com ports
if (comport_wr) wait_write <= din; // $xxEF
if (comport_wr || comport_rd) wait_addr <= a[15:8];
if ((loa==PORTXT) && (hoa == DMAWPA)) wait_addr <= din;
end
// wait from wait registers
// ACHTUNG!!!! here portxx_wr are ON Z80 CLOCK! logic must change when moving to clk strobes
assign wait_start_gluclock = (gluclock_on && !a[14] && (portf7_rd || portf7_wr)); // $BFF7 - gluclock r/w
assign wait_start_comport = (comport_rd || comport_wr);
endmodule

View File

@ -1,85 +0,0 @@
// Decoding and strobing of z80 signals
module zsignals
(
// clocks
input wire clk,
// z80 interface input
input wire iorq_n,
input wire mreq_n,
input wire m1_n,
input wire rfsh_n,
input wire rd_n,
input wire wr_n,
// Z80 signals
output wire m1,
output wire rfsh,
output wire rd,
output wire wr,
output wire iorq,
output wire mreq,
output wire rdwr,
output wire iord,
output wire iowr,
output wire iorw,
output wire memrd,
output wire memwr,
output wire memrw,
output wire opfetch,
output wire intack,
// Z80 signals strobes, at fclk
output wire iorq_s,
output wire mreq_s,
output wire iord_s,
output wire iowr_s,
output wire iorw_s,
output wire memrd_s,
output wire memwr_s,
output wire memrw_s,
output wire opfetch_s
);
// invertors
assign m1 = !m1_n;
assign rfsh = !rfsh_n;
assign rd = !rd_n;
assign wr = !wr_n;
// requests
assign iorq = !iorq_n && m1_n; // this is masked by ~M1 to avoid port decoding on INT ack
assign mreq = !mreq_n && rfsh_n; // this is masked by ~RFSH to ignore refresh cycles as memory requests
// combined
assign rdwr = rd || wr;
assign iord = iorq && rd;
assign iowr = iorq && wr;
assign iorw = iorq && rdwr;
assign memrd = mreq && rd;
assign memwr = mreq && !rd;
assign memrw = mreq && rdwr;
assign opfetch = memrd && m1;
assign intack = !iorq_n && m1; // NOT masked by M1
// strobed
assign iorq_s = iorq_r[0] && !iorq_r[1];
assign mreq_s = mreq_r[0] && !mreq_r[1];
assign iord_s = iorq_s && rd;
assign iowr_s = iorq_s && wr;
assign iorw_s = iorq_s && rdwr;
assign memrd_s = mreq_s && rd;
assign memwr_s = mreq_s && !rd;
assign memrw_s = mreq_s && rdwr;
assign opfetch_s = memrd_s && m1;
// latch inputs on FPGA clock
reg [1:0] iorq_r, mreq_r;
always @(posedge clk) begin
iorq_r <= {iorq_r[0], iorq};
mreq_r <= {mreq_r[0], mreq};
end
endmodule