diff --git a/cores/spectrum/data_io.v b/cores/spectrum/data_io.v index 309c3ce..2ce90a2 100644 --- a/cores/spectrum/data_io.v +++ b/cores/spectrum/data_io.v @@ -4,7 +4,9 @@ // io controller writable ram for the MiST board // http://code.google.com/p/mist-board/ // -// Copyright (c) 2014 Till Harbaum +// ZX Spectrum adapted version +// +// Copyright (c) 2015 Till Harbaum // // 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 \ No newline at end of file +endmodule diff --git a/cores/spectrum/divmmc.v b/cores/spectrum/divmmc.v index 875562f..2c45526 100644 --- a/cores/spectrum/divmmc.v +++ b/cores/spectrum/divmmc.v @@ -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 diff --git a/cores/spectrum/spectrum_mist.vhd b/cores/spectrum/spectrum_mist.vhd index be508f6..68a8d69 100755 --- a/cores/spectrum/spectrum_mist.vhd +++ b/cores/spectrum/spectrum_mist.vhd @@ -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; diff --git a/cores/spectrum/spi.v b/cores/spectrum/spi.v index 78caec9..d338b12 100644 --- a/cores/spectrum/spi.v +++ b/cores/spectrum/spi.v @@ -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