mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-08 17:01:18 +00:00
[SPECTRUM] Code cleanup and forced esxdos init at reboot
This commit is contained in:
@@ -4,7 +4,9 @@
|
||||
// io controller writable ram for the MiST board
|
||||
// http://code.google.com/p/mist-board/
|
||||
//
|
||||
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
|
||||
// ZX Spectrum adapted version
|
||||
//
|
||||
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// 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
|
||||
@@ -33,12 +35,13 @@ module data_io (
|
||||
// external ram interface
|
||||
input clk,
|
||||
output reg wr,
|
||||
output reg [24:0] a,
|
||||
output [24:0] a,
|
||||
output [7:0] d
|
||||
);
|
||||
|
||||
assign d = data;
|
||||
assign size = addr - 25'h100000;
|
||||
assign d = erasing?8'h00:data;
|
||||
assign size = addr - 25'h100000; // only valid for tape
|
||||
assign a = erasing?erase_addr:write_a;
|
||||
|
||||
// *********************************************************************************
|
||||
// spi client
|
||||
@@ -47,12 +50,15 @@ assign size = addr - 25'h100000;
|
||||
// this core supports only the display related OSD commands
|
||||
// of the minimig
|
||||
reg [6:0] sbuf;
|
||||
reg [7:0] cmd /* synthesis noprune */;
|
||||
reg [7:0] data /* synthesis noprune */;
|
||||
reg [4:0] cnt /* synthesis noprune */;
|
||||
reg [7:0] cmd;
|
||||
reg [7:0] data;
|
||||
reg [4:0] cnt;
|
||||
|
||||
reg [24:0] addr /* synthesis noprune */;
|
||||
reg rclk /* synthesis noprune */;
|
||||
reg [24:0] addr;
|
||||
reg [24:0] write_a;
|
||||
reg rclk;
|
||||
reg erase_trigger;
|
||||
reg [24:0] erase_addr;
|
||||
|
||||
localparam UIO_FILE_TX = 8'h53;
|
||||
localparam UIO_FILE_TX_DAT = 8'h54;
|
||||
@@ -60,6 +66,7 @@ localparam UIO_FILE_INDEX = 8'h55;
|
||||
|
||||
assign downloading = downloading_reg;
|
||||
reg downloading_reg = 1'b0;
|
||||
reg erasing = 1'b0;
|
||||
|
||||
// data_io has its own SPI interface to the io controller
|
||||
always@(posedge sck, posedge ss) begin
|
||||
@@ -67,6 +74,7 @@ always@(posedge sck, posedge ss) begin
|
||||
cnt <= 5'd0;
|
||||
else begin
|
||||
rclk <= 1'b0;
|
||||
erase_trigger <= 1'b0;
|
||||
|
||||
// don't shift in last bit. It is evaluated directly
|
||||
// when writing to ram
|
||||
@@ -93,15 +101,21 @@ always@(posedge sck, posedge ss) begin
|
||||
else addr <= 25'h200000; // tape buffer at 2MB
|
||||
|
||||
downloading_reg <= 1'b1;
|
||||
end else
|
||||
end else begin
|
||||
downloading_reg <= 1'b0;
|
||||
|
||||
// in case of a esxdos 8k download we also erase the memory
|
||||
// area at 1a0000 to make sure divmmc ram is empty
|
||||
if(addr == 25'h182000)
|
||||
erase_trigger <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
// command 0x54: UIO_FILE_TX
|
||||
if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin
|
||||
data <= {sbuf, sdi};
|
||||
rclk <= 1'b1;
|
||||
a <= addr;
|
||||
write_a <= addr;
|
||||
end
|
||||
|
||||
// expose file (menu) index
|
||||
@@ -111,14 +125,36 @@ always@(posedge sck, posedge ss) begin
|
||||
end
|
||||
|
||||
reg rclkD, rclkD2;
|
||||
reg eraseD, eraseD2;
|
||||
reg [4:0] erase_clk_div;
|
||||
always@(posedge clk) begin
|
||||
// bring rclk from spi clock domain into c64 clock domain
|
||||
rclkD <= rclk;
|
||||
rclkD2 <= rclkD;
|
||||
wr <= 1'b0;
|
||||
|
||||
if(rclkD && !rclkD2)
|
||||
if(rclkD && !rclkD2)
|
||||
wr <= 1'b1;
|
||||
|
||||
// download may trigger an erase afterwards
|
||||
eraseD <= erase_trigger;
|
||||
eraseD2 <= eraseD;
|
||||
|
||||
// start erasing
|
||||
if(eraseD && !eraseD2) begin
|
||||
erase_clk_div <= 5'd0;
|
||||
erase_addr <= 25'h1a0000;
|
||||
erasing <= 1'b1;
|
||||
end else begin
|
||||
erase_clk_div <= erase_clk_div + 5'd1;
|
||||
if(erase_clk_div == 0) begin
|
||||
if(erase_addr != 25'h1a2000) begin
|
||||
erase_addr <= erase_addr + 25'd1;
|
||||
wr <= 1'b1;
|
||||
end else
|
||||
erasing <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
endmodule
|
||||
|
||||
@@ -53,47 +53,40 @@ always @(posedge clk) begin
|
||||
paged_in <= 1'b0;
|
||||
ctrl <= 8'h00;
|
||||
end else begin
|
||||
// if(clken) begin
|
||||
if (a[3:0]==4'h3 && enable && !wr_n)
|
||||
ctrl <= din;
|
||||
spi_rx_strobe = 1'b0;
|
||||
spi_tx_strobe = 1'b0;
|
||||
|
||||
if(a[3:0]==4'h7 && enable && !wr_n)
|
||||
sd_cs <= din[0];
|
||||
|
||||
// SPI read
|
||||
if (enable && a[3:0]==4'hb && wr_n)
|
||||
spi_rx_strobe = 1'b1;
|
||||
else
|
||||
spi_rx_strobe = 1'b0;
|
||||
if (a[3:0]==4'h3 && enable && !wr_n)
|
||||
ctrl <= din;
|
||||
|
||||
// SPI write
|
||||
if (enable && a[3:0]==4'hb && !wr_n)
|
||||
spi_tx_strobe = 1'b1;
|
||||
else
|
||||
spi_tx_strobe = 1'b0;
|
||||
if(a[3:0]==4'h7 && enable && !wr_n)
|
||||
sd_cs <= din[0];
|
||||
|
||||
if (!mreq_n && !rd_n && !m1_n &&
|
||||
((a==16'h0000) || (a==16'h0008) || (a==16'h0038) ||
|
||||
(a==16'h0066) || (a==16'h04C6) || (a==16'h0562))) begin
|
||||
// automapper diferido (siguiente ciclo)
|
||||
m1_trigger <= 1'b1;
|
||||
end else if (!mreq_n && !rd_n && !m1_n && a[15:8]==8'h3D) begin
|
||||
// automapper no diferido (ciclo actual)
|
||||
paged_in <= 1'b1;
|
||||
m1_trigger <= 1'b1;
|
||||
end else if (!mreq_n && !rd_n && !m1_n && a[15:3]==13'b0001111111111) begin
|
||||
// desconexin de automapper diferido
|
||||
m1_trigger <= 1'b0;
|
||||
end
|
||||
// SPI read/write
|
||||
if(enable && a[3:0]==4'hb) begin
|
||||
if(wr_n) spi_rx_strobe = 1'b1;
|
||||
else spi_tx_strobe = 1'b1;
|
||||
end
|
||||
|
||||
if (!mreq_n && !rd_n && !m1_n &&
|
||||
((a==16'h0000) || (a==16'h0008) || (a==16'h0038) ||
|
||||
(a==16'h0066) || (a==16'h04C6) || (a==16'h0562))) begin
|
||||
// activate automapper after this cycle
|
||||
m1_trigger <= 1'b1;
|
||||
end else if (!mreq_n && !rd_n && !m1_n && a[15:8]==8'h3D) begin
|
||||
// activate automapper immediately
|
||||
paged_in <= 1'b1;
|
||||
m1_trigger <= 1'b1;
|
||||
end else if (!mreq_n && !rd_n && !m1_n && {a[15:3],3'd0} == 16'h1ff8) begin
|
||||
// deactivate automapper after this cycle
|
||||
m1_trigger <= 1'b0;
|
||||
end
|
||||
|
||||
if (m1_n==1'b1) begin // tras el ciclo M1, aqu es cuando realmente se hace el mapping
|
||||
paged_in <= m1_trigger;
|
||||
end
|
||||
// end
|
||||
if (m1_n==1'b1)
|
||||
paged_in <= m1_trigger;
|
||||
end
|
||||
end
|
||||
|
||||
// Instanciacion del modulo SPI
|
||||
spi mi_spi (
|
||||
.clk(clk),
|
||||
.tx_strobe(spi_tx_strobe),
|
||||
@@ -102,8 +95,8 @@ spi mi_spi (
|
||||
.dout(dout),
|
||||
|
||||
.spi_clk(sd_sck),
|
||||
.spi_di(sd_mosi),
|
||||
.spi_do(sd_miso)
|
||||
.spi_di(sd_miso),
|
||||
.spi_do(sd_mosi)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- * Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
-- this list of conditionand the following disclaimer.
|
||||
--
|
||||
-- * Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
@@ -51,9 +51,9 @@ generic (
|
||||
-- 0 = 48 K
|
||||
-- 1 = 128 K
|
||||
-- 2 = +2A/+3
|
||||
MODEL : integer := 2
|
||||
);
|
||||
|
||||
MODEL : integer := 1
|
||||
);
|
||||
|
||||
port (
|
||||
-- Clocks
|
||||
CLOCK_27 : in std_logic_vector(1 downto 0);
|
||||
@@ -192,7 +192,7 @@ end component;
|
||||
---------
|
||||
|
||||
-- config string used by the io controller to fill the OSD
|
||||
constant CONF_STR : string := "SPECTRUM;CSW;T1,Reset;T2,Trigger NMI;O3,ZXMMC+ overlay,Off,On;O4,ZXMMC+ memory,RAM,ROM";
|
||||
constant CONF_STR : string := "SPECTRUM;CSW;T1,Reset;T2,Trigger NMI";
|
||||
|
||||
-- convert string to std_logic_vector to be given to user_io
|
||||
function to_slv(s: string) return std_logic_vector is
|
||||
@@ -497,49 +497,41 @@ component sigma_delta_dac is
|
||||
);
|
||||
end component;
|
||||
|
||||
|
||||
-------------------
|
||||
-- MMC interface
|
||||
-- DIVMMC interface
|
||||
-------------------
|
||||
|
||||
component zxmmc is
|
||||
component divmmc is
|
||||
port (
|
||||
CLOCK : in std_logic;
|
||||
nRESET : in std_logic;
|
||||
CLKEN : in std_logic;
|
||||
|
||||
clk : in std_logic;
|
||||
reset_n : in std_logic;
|
||||
clken : in std_logic;
|
||||
|
||||
-- Bus interface
|
||||
ENABLE : in std_logic;
|
||||
-- 0 - W - Card chip selects (active low)
|
||||
-- 1 - RW - SPI tx/rx data register
|
||||
-- 2 - Not used
|
||||
-- 3 - RW - Paging control register
|
||||
RS : in std_logic_vector(1 downto 0);
|
||||
nWR : in std_logic;
|
||||
DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0);
|
||||
enable : in std_logic;
|
||||
a : in std_logic_vector(15 downto 0);
|
||||
wr_n : in std_logic;
|
||||
rd_n : in std_logic;
|
||||
mreq_n : in std_logic;
|
||||
m1_n : in std_logic;
|
||||
din : in std_logic_vector(7 downto 0);
|
||||
dout : out std_logic_vector(7 downto 0);
|
||||
|
||||
-- memory paging info
|
||||
paged_in : out std_logic;
|
||||
sram_page: out std_logic_vector(3 downto 0);
|
||||
mapram : out std_logic;
|
||||
conmem : out std_logic;
|
||||
|
||||
-- SD card interface
|
||||
SD_CS0 : out std_logic;
|
||||
SD_CS1 : out std_logic;
|
||||
SD_CLK : out std_logic;
|
||||
SD_MOSI : out std_logic;
|
||||
SD_MISO : in std_logic;
|
||||
|
||||
-- Paging control for external RAM/ROM banks
|
||||
EXT_WR_EN : out std_logic; -- Enable writes to external RAM/ROM
|
||||
EXT_RD_EN : out std_logic; -- Enable reads from external RAM/ROM (overlay internal ROM)
|
||||
EXT_ROM_nRAM : out std_logic; -- Select external ROM or RAM banks
|
||||
EXT_BANK : out std_logic_vector(4 downto 0); -- Selected bank number
|
||||
|
||||
-- DIP switches (reset values for corresponding bits above)
|
||||
INIT_RD_EN : in std_logic;
|
||||
INIT_ROM_nRAM : in std_logic;
|
||||
|
||||
-- Kempston joystick input
|
||||
JOYSTICK : in std_logic_vector(7 downto 0)
|
||||
sd_cs : out std_logic;
|
||||
sd_sck : out std_logic;
|
||||
sd_mosi : out std_logic;
|
||||
sd_miso : in std_logic
|
||||
);
|
||||
end component;
|
||||
|
||||
|
||||
-------------
|
||||
-- Signals
|
||||
-------------
|
||||
@@ -556,17 +548,18 @@ signal sdram_oe : std_logic;
|
||||
signal zx_red : std_logic_vector(5 downto 0);
|
||||
signal zx_green : std_logic_vector(5 downto 0);
|
||||
signal zx_blue : std_logic_vector(5 downto 0);
|
||||
signal zx_hs : std_logic;
|
||||
signal zx_vs : std_logic;
|
||||
|
||||
-- signals from user_io
|
||||
signal switches: std_logic_vector(1 downto 0);
|
||||
signal buttons: std_logic_vector(1 downto 0);
|
||||
signal joystickA: std_logic_vector(5 downto 0);
|
||||
signal joystickB: std_logic_vector(5 downto 0);
|
||||
signal joystickA: std_logic_vector(7 downto 0);
|
||||
signal joystickB: std_logic_vector(7 downto 0);
|
||||
signal status: std_logic_vector(7 downto 0);
|
||||
|
||||
-- TH extra
|
||||
signal divmmc_lo_addr : std_logic_vector(18 downto 0);
|
||||
signal divmmc_hi_addr : std_logic_vector(18 downto 0);
|
||||
signal divmmc_addr : std_logic_vector(18 downto 0);
|
||||
signal rom_addr : std_logic_vector(19 downto 0);
|
||||
signal ram_addr : std_logic_vector(19 downto 0);
|
||||
signal cpu_addr : std_logic_vector(20 downto 0);
|
||||
@@ -593,7 +586,7 @@ signal tape_download : std_logic;
|
||||
signal io_addr : std_logic_vector(24 downto 0);
|
||||
signal audio : std_logic;
|
||||
signal scandoubler_disable : std_logic;
|
||||
signal rom_dl : std_logic := '0';
|
||||
signal esxdos_downloaded : std_logic := '0';
|
||||
signal sd_lba : std_logic_vector(31 downto 0);
|
||||
signal sd_rd : std_logic;
|
||||
signal sd_wr : std_logic;
|
||||
@@ -604,6 +597,10 @@ signal sd_dout : std_logic_vector(7 downto 0);
|
||||
signal sd_dout_strobe : std_logic;
|
||||
signal sd_din : std_logic_vector(7 downto 0);
|
||||
signal sd_din_strobe : std_logic;
|
||||
signal divmmc_paged_in : std_logic;
|
||||
signal divmmc_sram_page: std_logic_vector(3 downto 0);
|
||||
signal divmmc_mapram : std_logic;
|
||||
signal divmmc_conmem : std_logic;
|
||||
|
||||
-- Master clock - 28 MHz
|
||||
signal clk112 : std_logic;
|
||||
@@ -631,8 +628,9 @@ signal page_enable : std_logic; -- all odd IO addresses with A15 and A1 clear (
|
||||
signal psg_enable : std_logic; -- all odd IO addresses with A15 set and A1 clear
|
||||
-- +3 extensions
|
||||
signal plus3_enable : std_logic; -- A15, A14, A13, A1 clear, A12 set.
|
||||
-- ZXMMC
|
||||
signal zxmmc_enable : std_logic; -- A4-A0 set
|
||||
-- MMC
|
||||
signal divmmc_enable : std_logic; -- A7-A4 = "1110"
|
||||
signal kempston_enable : std_logic; -- A7-A0 = "00011111"
|
||||
|
||||
-- 128K paging register (with default values for systems that don't have it)
|
||||
signal page_reg_disable : std_logic := '1'; -- bit 5
|
||||
@@ -709,19 +707,13 @@ signal psg_bdir : std_logic;
|
||||
signal psg_bc1 : std_logic;
|
||||
signal psg_aout : std_logic_vector(7 downto 0) := "00000000";
|
||||
|
||||
-- ZXMMC interface
|
||||
signal zxmmc_do : std_logic_vector(7 downto 0);
|
||||
-- DIVMMC interface
|
||||
signal divmmc_do : std_logic_vector(7 downto 0);
|
||||
|
||||
signal zxmmc_sclk : std_logic;
|
||||
signal zxmmc_mosi : std_logic;
|
||||
signal zxmmc_miso : std_logic;
|
||||
signal zxmmc_cs0 : std_logic;
|
||||
|
||||
-- ZXMMC+ external ROM/RAM interface (for ResiDOS)
|
||||
signal zxmmc_wr_en : std_logic;
|
||||
signal zxmmc_rd_en : std_logic;
|
||||
signal zxmmc_rom_nram : std_logic;
|
||||
signal zxmmc_bank : std_logic_vector(4 downto 0);
|
||||
signal divmmc_sclk : std_logic;
|
||||
signal divmmc_mosi : std_logic;
|
||||
signal divmmc_miso : std_logic;
|
||||
signal divmmc_cs : std_logic;
|
||||
|
||||
begin
|
||||
-- 28 MHz master clock
|
||||
@@ -804,7 +796,7 @@ begin
|
||||
begin
|
||||
if rising_edge(ioctl_download) then
|
||||
if(ioctl_index = "00000") then
|
||||
rom_dl <= '1';
|
||||
esxdos_downloaded <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
@@ -821,7 +813,7 @@ begin
|
||||
|
||||
audio_out => ula_ear_in,
|
||||
|
||||
downloading => ioctl_download,
|
||||
downloading => tape_download,
|
||||
size => ioctl_size,
|
||||
|
||||
-- ram interface
|
||||
@@ -876,8 +868,8 @@ begin
|
||||
conf_str => to_slv(CONF_STR),
|
||||
|
||||
status => status,
|
||||
joystick_0(5 downto 0) => joystickA,
|
||||
joystick_1(5 downto 0) => joystickB,
|
||||
joystick_0 => joystickA,
|
||||
joystick_1 => joystickB,
|
||||
switches => switches,
|
||||
buttons => buttons,
|
||||
scandoubler_disable => scandoubler_disable,
|
||||
@@ -913,13 +905,13 @@ begin
|
||||
io_dout => sd_din,
|
||||
io_dout_strobe => sd_din_strobe,
|
||||
|
||||
allow_sdhc => '0', -- SPECTRUM does not support SDHC
|
||||
allow_sdhc => '1', -- esxdos supports SDHC
|
||||
|
||||
-- connection to host
|
||||
sd_cs => zxmmc_cs0,
|
||||
sd_sck => zxmmc_sclk,
|
||||
sd_sdi => zxmmc_mosi,
|
||||
sd_sdo => zxmmc_miso
|
||||
sd_cs => divmmc_cs,
|
||||
sd_sck => divmmc_sclk,
|
||||
sd_sdi => divmmc_mosi,
|
||||
sd_sdo => divmmc_miso
|
||||
);
|
||||
|
||||
-- CPU
|
||||
@@ -936,7 +928,8 @@ begin
|
||||
cpu_irq_n <= vid_irq_n;
|
||||
-- Unused CPU input signals
|
||||
cpu_wait_n <= '1';
|
||||
cpu_nmi_n <= '0' when status(2) = '1' else '1';
|
||||
-- trigger nmi either with the OSD or with the joystick
|
||||
cpu_nmi_n <= '0' when status(2) = '1' or joystickA(7) = '1' or joystickB(7) = '1' else '1';
|
||||
cpu_busreq_n <= '1';
|
||||
|
||||
-- Keyboard
|
||||
@@ -1010,29 +1003,28 @@ begin
|
||||
|
||||
end generate;
|
||||
|
||||
-- ZXMMC interface
|
||||
mmc: zxmmc port map (
|
||||
|
||||
-- DIVMMC interface
|
||||
dmmc: divmmc port map (
|
||||
clock, reset_n, cpu_clken,
|
||||
zxmmc_enable, cpu_a(6 downto 5), -- A6/A5 selects register
|
||||
cpu_wr_n, cpu_do, zxmmc_do,
|
||||
zxmmc_cs0, open,
|
||||
zxmmc_sclk, zxmmc_mosi, zxmmc_miso,
|
||||
zxmmc_wr_en, zxmmc_rd_en, zxmmc_rom_nram,
|
||||
zxmmc_bank,
|
||||
status(3),status(4),
|
||||
-- map both joysticks onto the one supported by kempston
|
||||
"00" & (joystickA or joystickB)
|
||||
divmmc_enable, cpu_a,
|
||||
cpu_wr_n, cpu_rd_n, cpu_mreq_n, cpu_m1_n,
|
||||
cpu_do, divmmc_do,
|
||||
divmmc_paged_in, divmmc_sram_page, divmmc_mapram, divmmc_conmem,
|
||||
divmmc_cs, divmmc_sclk, divmmc_mosi, divmmc_miso
|
||||
);
|
||||
|
||||
-- Asynchronous reset
|
||||
-- System is reset by external reset switch or PLL being out of lock
|
||||
|
||||
-- delay reset so sdram can be initialized etc
|
||||
-- delay reset so sdram can be initialized etc. especially clearing the
|
||||
-- divmmc ram after esxdos upload needs some time (9.3ms)
|
||||
-- counting to 280000 at 28Mhz is 10ms
|
||||
process(clock, pll_locked, status, buttons)
|
||||
variable reset_cnt : integer range 0 to 10000;
|
||||
variable reset_cnt : integer range 0 to 280000;
|
||||
begin
|
||||
if pll_locked = '0' or status(0) = '1' or status(1) = '1' or buttons(1) = '1' then
|
||||
reset_cnt := 10000;
|
||||
reset_cnt := 280000;
|
||||
elsif rising_edge(clock) then
|
||||
if reset_cnt /= 0 then
|
||||
reset_cnt := reset_cnt - 1;
|
||||
@@ -1059,13 +1051,14 @@ begin
|
||||
-- 0x1FFD W = +3 paging and control register
|
||||
-- 0x2FFD R = +3 FDC status register
|
||||
-- 0x3FFD R/W = +3 FDC data register
|
||||
-- 0xXXXF R/W = ZXMMC interface
|
||||
-- 0xXXEX R/W = DIVMMC interface
|
||||
-- FIXME: Revisit this - could be neater
|
||||
ula_enable <= (not cpu_ioreq_n) and not cpu_a(0); -- all even IO addresses
|
||||
psg_enable <= (not cpu_ioreq_n) and cpu_a(0) and cpu_a(15) and not cpu_a(1);
|
||||
zxmmc_enable <= (not cpu_ioreq_n) and cpu_a(4) and cpu_a(3) and cpu_a(2) and cpu_a(1) and cpu_a(0);
|
||||
ula_enable <= (not cpu_ioreq_n) and cpu_m1_n and not cpu_a(0); -- all even IO addresses
|
||||
psg_enable <= (not cpu_ioreq_n) and cpu_m1_n and cpu_a(0) and cpu_a(15) and not cpu_a(1);
|
||||
kempston_enable <= (not cpu_ioreq_n) and cpu_m1_n and not cpu_a(7) and not cpu_a(6) and not cpu_a(5) and cpu_a(4) and cpu_a(3) and cpu_a(2) and cpu_a(1) and cpu_a(0);
|
||||
divmmc_enable <= esxdos_downloaded and (not cpu_ioreq_n) and cpu_m1_n and cpu_a(7) and cpu_a(6) and cpu_a(5) and not cpu_a(4) and cpu_a(0);
|
||||
addr_decode_128k: if model /= 2 generate
|
||||
page_enable <= (not cpu_ioreq_n) and cpu_a(0) and not (cpu_a(15) or cpu_a(1));
|
||||
page_enable <= (not cpu_ioreq_n) and cpu_m1_n and cpu_a(0) and not (cpu_a(15) or cpu_a(1));
|
||||
end generate;
|
||||
addr_decode_plus3: if model = 2 generate
|
||||
-- Paging register address decoding is slightly stricter on the +3
|
||||
@@ -1104,62 +1097,72 @@ begin
|
||||
|
||||
process(cpu_cycle)
|
||||
begin
|
||||
-- latch data at the end of cpus memory cycle
|
||||
-- latch sdram data at the end of cpus memory cycle
|
||||
if falling_edge(cpu_cycle) then
|
||||
if rom_enable = '1' then
|
||||
-- fetch rom from internal memory unless something has
|
||||
-- been uploaded. Then use uploaded code in ram
|
||||
if(rom_dl = '0') then
|
||||
mem_do <= rom_do;
|
||||
else
|
||||
mem_do <= sdram_do;
|
||||
end if;
|
||||
else
|
||||
mem_do <= sdram_do;
|
||||
end if;
|
||||
mem_do <= sdram_do;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- CPU data bus mux
|
||||
cpu_di <=
|
||||
-- System RAM
|
||||
mem_do when ram_enable = '1' else
|
||||
-- External (ZXMMC+) RAM at 0x0000-0x3fff when enabled
|
||||
-- This overlays the internal ROM
|
||||
mem_do when rom_enable = '1' and zxmmc_rd_en = '1' and zxmmc_rom_nram = '0' else
|
||||
-- Internal ROM or external (ZXMMC+) ROM at 0x0000-0x3fff
|
||||
mem_do when rom_enable = '1' else
|
||||
mem_do when ram_enable = '1' else
|
||||
-- DIVMMC memory mapped into ROM area
|
||||
mem_do when rom_enable = '1' and divmmc_paged_in = '1' and esxdos_downloaded = '1' else
|
||||
-- Internal ROM
|
||||
rom_do when rom_enable = '1' else
|
||||
-- IO ports
|
||||
ula_do when ula_enable = '1' else
|
||||
psg_do when psg_enable = '1' else
|
||||
zxmmc_do when zxmmc_enable = '1' else
|
||||
divmmc_do when divmmc_enable = '1' else
|
||||
-- map both joysticks onto the one supported by kempston
|
||||
"00" & (joystickA(5 downto 0) or joystickB(5 downto 0))
|
||||
when kempston_enable = '1' else
|
||||
-- Idle bus
|
||||
(others => '1');
|
||||
|
||||
rom_48k: if model = 0 generate
|
||||
-- 48K
|
||||
rom_addr <=
|
||||
-- Overlay external ROMs when enabled
|
||||
"1" & zxmmc_bank & cpu_a(13 downto 0)
|
||||
when zxmmc_rd_en = '1' else
|
||||
-- Otherwise access the internal ROM
|
||||
"000000" & cpu_a(13 downto 0);
|
||||
end generate;
|
||||
rom_128k: if model = 1 generate
|
||||
-- DIVMMC low mapping (0x0000 - 0x1fff)
|
||||
divmmc_lo_addr <= "000000" & cpu_a(12 downto 0) when
|
||||
divmmc_conmem = '1' or divmmc_mapram = '0' else "010011" & cpu_a(12 downto 0);
|
||||
|
||||
-- DIVMMC hi mapping (0x2000 - 0x3fff)
|
||||
divmmc_hi_addr <= "01" & divmmc_sram_page & cpu_a(12 downto 0);
|
||||
|
||||
-- DIVMMC mapping
|
||||
divmmc_addr <= divmmc_lo_addr when cpu_a(13) = '0' else divmmc_hi_addr;
|
||||
|
||||
-- 128K
|
||||
rom_addr <=
|
||||
-- Overlay external ROMs when enabled
|
||||
"1" & zxmmc_bank & cpu_a(13 downto 0)
|
||||
when zxmmc_rd_en = '1' else
|
||||
-- all DIVMMC mapping (even ram) happens in the ROM
|
||||
-- address space (0x0000-0x3fff)
|
||||
"1" & divmmc_addr when esxdos_downloaded = '1' and divmmc_paged_in = '1' else
|
||||
-- Otherwise access the internal ROMs
|
||||
"00000" & page_rom_sel & cpu_a(13 downto 0);
|
||||
end generate;
|
||||
rom_plus3: if model = 2 generate
|
||||
-- DIVMMC low mapping (0x0000 - 0x1fff)
|
||||
divmmc_lo_addr <= "000000" & cpu_a(12 downto 0) when
|
||||
divmmc_conmem = '1' or divmmc_mapram = '0' else "010011" & cpu_a(12 downto 0);
|
||||
|
||||
-- DIVMMC hi mapping (0x2000 - 0x3fff)
|
||||
divmmc_hi_addr <= "01" & divmmc_sram_page & cpu_a(12 downto 0);
|
||||
|
||||
-- DIVMMC mapping
|
||||
divmmc_addr <= divmmc_lo_addr when cpu_a(13) = '0' else divmmc_hi_addr;
|
||||
|
||||
-- +3
|
||||
rom_addr <=
|
||||
-- Overlay external ROMs when enabled
|
||||
"1" & zxmmc_bank & cpu_a(13 downto 0)
|
||||
when zxmmc_rd_en = '1' else
|
||||
-- all DIVMMC mapping (even ram) happens in the ROM
|
||||
-- address space (0x0000-0x3fff)
|
||||
"1" & divmmc_addr when esxdos_downloaded = '1' and divmmc_paged_in = '1' else
|
||||
|
||||
-- Otherwise access the internal ROMs
|
||||
"0000" & plus3_page(1) & page_rom_sel & cpu_a(13 downto 0);
|
||||
end generate;
|
||||
@@ -1169,9 +1172,7 @@ begin
|
||||
|
||||
-- first 1MB of sdram are used as ram, second 1MB sdram are used as rom
|
||||
-- and after that starts tape buffer
|
||||
cpu_addr <= "0" & ram_addr when ram_enable = '1' or
|
||||
(rom_enable = '1' and zxmmc_rd_en = '1' and zxmmc_rom_nram = '0') else
|
||||
"1" & rom_addr;
|
||||
cpu_addr <= "0" & ram_addr when ram_enable = '1' else "1" & rom_addr;
|
||||
|
||||
-- Video from bank 7 (128K/+3)
|
||||
-- Video from bank 5
|
||||
@@ -1189,16 +1190,29 @@ begin
|
||||
|
||||
-- Synchronous outputs to SRAM
|
||||
process(clock,reset_n)
|
||||
variable ext_ram_write : std_logic; -- External RAM (ZXMMC+)
|
||||
variable divmmc_lo_write : std_logic;
|
||||
variable divmmc_hi_write : std_logic;
|
||||
variable divmmc_write : std_logic;
|
||||
variable ext_ram_write : std_logic; -- External RAM
|
||||
variable int_ram_write : std_logic; -- Internal RAM
|
||||
variable sram_write : std_logic;
|
||||
begin
|
||||
ext_ram_write := (rom_enable and zxmmc_wr_en and not zxmmc_rom_nram) and not cpu_wr_n;
|
||||
-- never write to lower 8k
|
||||
divmmc_lo_write := '0';
|
||||
|
||||
-- write to upper 8k unless comem = 0, mapram = 1 and bank = 3
|
||||
divmmc_hi_write := not (divmmc_conmem and divmmc_mapram and
|
||||
not divmmc_sram_page(3) and not divmmc_sram_page(2) and
|
||||
divmmc_sram_page(1) and divmmc_sram_page(0));
|
||||
|
||||
-- access to first or second 8k in OS ROM area
|
||||
divmmc_write := (not cpu_a(13) and divmmc_lo_write) or
|
||||
( cpu_a(13) and divmmc_hi_write);
|
||||
|
||||
ext_ram_write := (rom_enable and esxdos_downloaded and divmmc_paged_in and divmmc_write) and not cpu_wr_n;
|
||||
int_ram_write := ram_enable and not cpu_wr_n;
|
||||
sram_write := int_ram_write or ext_ram_write;
|
||||
|
||||
-- if reset_n = '0' then
|
||||
-- els
|
||||
if rising_edge(clock) then
|
||||
-- synchonize cpu memory access to video memory access
|
||||
if vid_clken = '1' then
|
||||
@@ -1209,16 +1223,9 @@ begin
|
||||
-- Register SRAM signals to outputs (clock must be at least 2x CPU clock)
|
||||
if vid_clken = '1' then
|
||||
-- Fetch data from previous CPU cycle
|
||||
if rom_enable = '0' then
|
||||
-- Normal RAM access at 0x4000-0xffff
|
||||
-- 16-bit address
|
||||
ram_addr <= "000" & ram_page & cpu_a(13 downto 0);
|
||||
else
|
||||
-- ZXMMC+ external RAM access (16 banks of 16KB)
|
||||
-- at 0x0000-0x3fff
|
||||
-- 16-bit address
|
||||
ram_addr <= "1" & zxmmc_bank & cpu_a(13 downto 0);
|
||||
end if;
|
||||
-- Normal RAM access at 0x4000-0xffff
|
||||
-- 16-bit address
|
||||
ram_addr <= "000" & ram_page & cpu_a(13 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
@@ -1279,16 +1286,12 @@ begin
|
||||
end process;
|
||||
end generate;
|
||||
|
||||
-- Connect audio to PCM interface
|
||||
-- pcm_outl <= ula_ear_out & psg_aout & ula_mic_out & "000000";
|
||||
-- pcm_outr <= ula_ear_out & psg_aout & ula_mic_out & "000000";
|
||||
|
||||
-- Connect ULA to video output
|
||||
zx_red <= vid_r_out & "00";
|
||||
zx_green <= vid_g_out & "00";
|
||||
zx_blue <= vid_b_out & "00";
|
||||
zx_hs <= vid_hcsync_n;
|
||||
zx_vs <= vid_vsync_n;
|
||||
VGA_HS <= vid_hcsync_n;
|
||||
VGA_VS <= vid_vsync_n;
|
||||
|
||||
-- route video through osd
|
||||
osd_d : osd
|
||||
@@ -1307,8 +1310,6 @@ begin
|
||||
|
||||
red_out => VGA_R,
|
||||
green_out => VGA_G,
|
||||
blue_out => VGA_B,
|
||||
hs_out => VGA_HS,
|
||||
vs_out => VGA_VS
|
||||
blue_out => VGA_B
|
||||
);
|
||||
end architecture;
|
||||
|
||||
@@ -1,74 +1,35 @@
|
||||
// spi.v inspired by zxuno project
|
||||
|
||||
module spi (
|
||||
input wire clk, // 7MHz
|
||||
input wire tx_strobe, // a 1 para indicar que queremos enviar un dato por SPI
|
||||
input wire rx_strobe,// a 1 para indicar que queremos recibir un dato
|
||||
input wire [7:0] din, // del bus de datos de salida de la CPU
|
||||
input clk, // 7MHz
|
||||
input tx_strobe, // Byte ready to be transmitted
|
||||
input rx_strobe, // request to read one byte
|
||||
input [7:0] din, // del bus de datos de salida de la CPU
|
||||
output reg [7:0] dout, // al bus de datos de entrada de la CPU
|
||||
|
||||
output wire spi_clk, // Interface SPI
|
||||
output wire spi_di, //
|
||||
input wire spi_do //
|
||||
);
|
||||
output spi_clk, // spi itself
|
||||
input spi_di, //
|
||||
output spi_do //
|
||||
);
|
||||
|
||||
// Modulo SPI.
|
||||
reg ciclo_lectura = 1'b0; // ciclo de lectura en curso
|
||||
reg ciclo_escritura = 1'b0; // ciclo de escritura en curso
|
||||
reg [4:0] contador = 5'b00000; // contador del FSM (ciclos)
|
||||
reg [7:0] data_to_spi; // dato a enviar a la spi por DI
|
||||
reg [7:0] data_from_spi; // dato a recibir desde la spi
|
||||
reg [7:0] data_to_cpu; // ultimo dato recibido correctamente
|
||||
reg [4:0] counter = 5'd16; // tx/rx counter is idle
|
||||
reg [7:0] io_byte;
|
||||
|
||||
assign spi_clk = contador[0]; // spi_CLK es la mitad que el reloj del módulo
|
||||
assign spi_di = data_to_spi[7]; // la transmisión es del bit 7 al 0
|
||||
assign spi_clk = counter[0];
|
||||
assign spi_do = io_byte[7]; // data is shifted up during transfer
|
||||
wire io_strobe = tx_strobe || rx_strobe;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (tx_strobe && !ciclo_escritura) begin // si ha sido señalizado, iniciar ciclo de escritura
|
||||
ciclo_escritura <= 1'b1;
|
||||
ciclo_lectura <= 1'b0;
|
||||
contador <= 5'b00000;
|
||||
data_to_spi <= din;
|
||||
end
|
||||
else if (rx_strobe && !ciclo_lectura) begin // si no, si mirar si hay que iniciar ciclo de lectura
|
||||
ciclo_lectura <= 1'b1;
|
||||
ciclo_escritura <= 1'b0;
|
||||
contador <= 5'b00000;
|
||||
data_to_cpu <= data_from_spi;
|
||||
data_from_spi <= 8'h00;
|
||||
data_to_spi <= 8'hFF; // mientras leemos, MOSI debe estar a nivel alto!
|
||||
end
|
||||
|
||||
// FSM para enviar un dato a la spi
|
||||
else if (ciclo_escritura==1'b1) begin
|
||||
if (contador!=5'b10000) begin
|
||||
if (spi_clk==1'b1) begin
|
||||
data_to_spi <= {data_to_spi[6:0],1'b0};
|
||||
data_from_spi <= {data_from_spi[6:0],spi_do};
|
||||
end
|
||||
contador <= contador + 1;
|
||||
end
|
||||
else begin
|
||||
if (!tx_strobe)
|
||||
ciclo_escritura <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// FSM para leer un dato de la spi
|
||||
else if (ciclo_lectura==1'b1) begin
|
||||
if (contador!=5'b10000) begin
|
||||
if (spi_clk==1'b1)
|
||||
data_from_spi <= {data_from_spi[6:0],spi_do};
|
||||
contador <= contador + 1;
|
||||
end
|
||||
else begin
|
||||
if (!rx_strobe)
|
||||
ciclo_lectura <= 1'b0;
|
||||
end
|
||||
end
|
||||
always @(posedge clk) begin
|
||||
// spi engine idle and is supposed to be started?
|
||||
if (io_strobe && (counter == 16)) begin
|
||||
// kickstart engine
|
||||
counter <= 5'd0;
|
||||
dout <= io_byte;
|
||||
io_byte <= tx_strobe?din:8'hff;
|
||||
end else if(counter != 16) begin
|
||||
if(spi_clk) io_byte <= { io_byte[6:0], spi_di };
|
||||
counter <= counter + 5'd1;
|
||||
end
|
||||
|
||||
always @* begin
|
||||
if (rx_strobe) begin
|
||||
dout = data_to_cpu;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user