Files
linuxcnc/5i24/configs/hostmot2/source/TopGCSPIHostMot2.vhd
Thaddeus-Maximus f3953d66ae ?
2026-04-03 15:58:58 -05:00

638 lines
21 KiB
VHDL
Executable File

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.MATH_REAL.ALL;
--
-- Copyright (C) 2007, Peter C. Wallace, Mesa Electronics
-- http://www.mesanet.com
--
-- This program is is licensed under a disjunctive dual license giving you
-- the choice of one of the two following sets of free software/open source
-- licensing terms:
--
-- * GNU General Public License (GPL), version 2.0 or later
-- * 3-clause BSD License
--
--
-- The GNU GPL License:
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
--
--
-- The 3-clause BSD License:
--
-- Redistribution and use in source and binary forms, with or without
-- 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.
--
-- * Redistributions in binary form must reproduce the above
-- copyright notice, this list of conditions and the following
-- disclaimer in the documentation and/or other materials
-- provided with the distribution.
--
-- * Neither the name of Mesa Electronics nor the names of its
-- contributors may be used to endorse or promote products
-- derived from this software without specific prior written
-- permission.
--
--
-- Disclaimer:
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
Library UNISIM;
use UNISIM.vcomponents.all;
-- dont change these:
use work.IDROMConst.all;
use work.decodedstrobe.all;
use work.FixICap.all;
-------------------- option selection area ----------------------------
-------------------- select one card type------------------------------
use work.@Card@.all;
--use work.i90_x9card.all; -- needs 7i90spi.ucf and SP6 x9 144 pin
--use work.c80_x9card.all; -- needs 7c80spi.ucf and SP6 x9 144 pin
--use work.c81_x9card.all; -- needs 7c81spi.ucf and SP6 x9 144 pin
-----------------------------------------------------------------------
--use work.@Pin@.all;
--72 pin pinouts for 7I90
--use work.PIN_JUSTIO_72.all;
--use work.PIN_SVST8_4IM2_72.all;
--use work.PIN_SVST8_4_72.all;
--use work.PIN_SVST4_8_72.all;
--use work.PIN_SVST4_8_ADO_72.all;
--use work.PIN_SVST8_8IM2_72.all;
--use work.PIN_SVST1_4_7I47S_72.all;
--use work.PIN_SVST2_4_7I47_72.all;
--use work.PIN_SVST1_5_7I47_72.all;
--use work.PIN_2X7I65_72.all;
--use work.PIN_ST12_72.all;
--use work.PIN_SV12_72.all;
--use work.PIN_SVST8_12_2x7I47_72.all;
--use work.PIN_SVSP8_6_7I46_72.all;
--use work.PIN_24XQCTRONLY_72.all;
--use work.PIN_2X7I65_72.all;
--use work.PIN_SV12IM_2X7I48_72.all;
--use work.PIN_SV6_7I49_72.all;
--use work.PIN_SVUA8_4_72.all;
--use work.PIN_SVUA8_8_72.all; -- 7I44 pinout UARTS
--use work.PIN_DA2_72.all;
--use work.PIN_SVST4_8_ADO_72.all;
--use work.PIN_SVSS8_8_72.all;
--use work.PIN_SSSVST8_8_8_72.all;
--use work.PIN_SVSS6_6_72.all;
--use work.PIN_SVSSST6_6_12_72.all;
--use work.PIN_SVSS6_8_72.all;
--use work.PIN_SSSVST8_1_5_7I47_72.all;
--use work.PIN_SVSS8_44_72.all;
--use work.PIN_RMSVSS6_8_72.all;
--use work.PIN_RMSVSS6_12_8_72.all; -- 4i69 5i24 only
--use work.PIN_ST8_PLASMA_72.all;
--use work.PIN_SV4_7I47S_72.all;
--use work.PIN_SVSTUA6_6_6_7I48_72.all;
--use work.PIN_SVSTTP6_6_7I39_72.all;
--use work.PIN_ST18_72.all;
--use work.PIN_SSST8_6_72.all;
--use work.PIN_STSVSS6_6_4_72.all;
-- 54 pin pinouts for 7C80
--use work.PIN_7C80D_54.all;
-- 57 pin pinouts for 7C81
--use work.PIN_JUSTIO_57.all;
--use work.PIN_5ABOBx3D_57.all;
--use work.PIN_5ABOBx2D_57.all;
--use work.PIN_MX3660x2D_57.all;
--use work.PIN_C11Gx2D_57.all;
--use work.PIN_G540x2D_57.all;
--use work.PIN_7I76x2D_57.all;
--use work.PIN_7I76x2_7I89D_57.all;
--use work.PIN_7I77x2D_57.all;
--use work.PIN_7I77x1_7I76x1D_57.all;
----------------------------------------------------------------------
-- dont change anything below unless you know what you are doing -----
entity TopGCSPIHostMot2 is -- for 7I90/7C80/7C81 in SPI mode
generic
(
ThePinDesc: PinDescType := PinDesc;
TheModuleID: ModuleIDType := ModuleID;
PWMRefWidth: integer := 13; -- PWM resolution is PWMRefWidth-1 bits
IDROMType: integer := 3;
UseIRQLogic: boolean := true;
UseWatchDog: boolean := true;
OffsetToModules: integer := 64;
OffsetToPinDesc: integer := 448;
BusWidth: integer := 32;
AddrWidth: integer := 16;
InstStride0: integer := 4; -- instance stride 0 = 4 bytes = 1 x 32 bit
InstStride1: integer := 64; -- instance stride 1 = 64 bytes = 16 x 32 bit registers
RegStride0: integer := 256; -- register stride 0 = 256 bytes = 64 x 32 bit registers
RegStride1: integer := 256; -- register stride 1 = 256 bytes - 64 x 32 bit
FallBack: boolean := false -- is this a fallback config?
);
Port ( CLK : in std_logic;
LEDS : out std_logic_vector(LEDCount -1 downto 0);
IOBITS : inout std_logic_vector(IOWidth -1 downto 0);
COM_SPICLK : in std_logic; -- host interface SPI ( FPGA is slave)
COM_SPIIN : in std_logic;
COM_SPIOUT : out std_logic;
COM_SPICS : in std_logic;
TEST0 : out std_logic;
RECONFIG : out std_logic;
NINIT : out std_logic;
SPICLK : out std_logic; -- config flash spi interface (FPGA is master)
SPIIN : in std_logic;
SPIOUT : out std_logic;
SPICS : out std_logic
);
end TopGCSPIHostMot2;
architecture Behavioral of TopGCSPIHostMot2 is
constant SPIRead : std_logic_vector(3 downto 0) := x"A";
constant SPIWrite : std_logic_vector(3 downto 0) := x"B";
constant SPITimeoutR : real := round(real(ClockLow)*0.000050); -- 50 usec default SPI timeout
constant SPITimeout : std_logic_vector(15 downto 0) := std_logic_vector(to_unsigned(integer(SPITimeoutR),16));
signal obus : std_logic_vector(31 downto 0);
signal translateaddr : std_logic_vector(AddrWidth-1 downto 0);
alias translatestrobe : std_logic is translateaddr(AddrWidth-1);
signal loadtranslateram : std_logic;
signal readtranslateram : std_logic;
signal translateramsel : std_logic;
signal loadspics : std_logic;
signal readspics : std_logic;
signal loadspireg : std_logic;
signal readspireg : std_logic;
signal Read32 : std_logic;
signal Write32Pipe : std_logic_vector(3 downto 0);
alias Write32: std_logic is Write32Pipe(3);
signal ReconfigSel : std_logic;
signal fooidata: std_logic_vector(7 downto 0);
signal ReConfigreg : std_logic := '0';
signal blinkcount : std_logic_vector(25 downto 0);
-- SPI interface signals
signal SPIRegIn : std_logic_vector(31 downto 0);
signal SPIRegOut : std_logic_vector(31 downto 0);
signal HM2DataOut : std_logic_vector(31 downto 0);
signal HM2DataOutL : std_logic_vector(31 downto 0);
signal HM2DataInL : std_logic_vector(31 downto 0);
signal AddrPtr : std_logic_vector(15 downto 0);
signal SyncAddrPtr : std_logic_vector(15 downto 0);
signal SPIBitCount : std_logic_vector(4 downto 0);
signal SPIHeader : std_logic;
signal DCOM_SPICS : std_logic;
signal SPICommand : std_logic_vector(3 downto 0);
signal SPIBurstCount : std_logic_vector(6 downto 0);
signal SPIAutoInc : std_logic;
signal FrameTimer : std_logic_vector(15 downto 0);
alias FrameTimerMSB : std_logic is FrameTimer(15);
signal FrameTimerMSBD : std_logic;
signal SPIReadRequest : std_logic;
signal SPIReadRequest1 : std_logic;
signal SPIReadRequest2 : std_logic;
signal SPIWriteRequest : std_logic;
signal SPIWriteRequest1 : std_logic;
signal SPIWriteRequest2 : std_logic;
signal SPIHeaderFlag : std_logic;
signal SPIHeaderFlag1 : std_logic;
signal SPIHeaderFlag2 : std_logic;
signal UpdateSPIReg : std_logic;
signal UpdateSPIRegD : std_logic;
signal NeedWrite : std_logic;
-- ICap interface
signal LoadICap : std_logic;
signal ReadICapCookie : std_logic;
signal ICapI : std_logic_vector(15 downto 0);
signal ICapClock : std_logic;
signal ICapTimer : std_logic_vector(5 downto 0) := "000000";
signal fclk : std_logic;
signal clkfx0: std_logic;
signal clk0_0: std_logic;
signal clklow : std_logic;
signal clkfx1: std_logic;
signal clk0_1: std_logic;
begin
ahostmot2: entity work.HostMot2
generic map (
thepindesc => ThePinDesc,
themoduleid => TheModuleID,
idromtype => IDROMType,
sepclocks => SepClocks,
onews => OneWS,
useirqlogic => UseIRQLogic,
pwmrefwidth => PWMRefWidth,
usewatchdog => UseWatchDog,
offsettomodules => OffsetToModules,
offsettopindesc => OffsetToPinDesc,
clockhigh => ClockHigh,
clockmed => ClockMed,
clocklow => ClockLow,
boardnamelow => BoardNameLow,
boardnamehigh => BoardNameHigh,
fpgasize => FPGASize,
fpgapins => FPGAPins,
ioports => IOPorts,
iowidth => IOWidth,
liowidth => LIOWidth,
portwidth => PortWidth,
buswidth => BusWidth,
addrwidth => AddrWidth,
inststride0 => InstStride0,
inststride1 => InstStride1,
regstride0 => RegStride0,
regstride1 => RegStride1,
ledcount => LEDCount )
port map (
ibus => HM2DataInL,
obus => HM2DataOut,
addr => SyncAddrPtr(AddrWidth-1 downto 2),
readstb => read32,
writestb => write32,
clklow => clklow, -- I/O clock
clkmed => clklow, -- Processor clock
clkhigh => fclk, -- PWM clock
-- int => INT,
iobits => IOBITS,
leds => LEDS
);
ClockMultH : DCM
generic map (
CLKDV_DIVIDE => 2.0,
CLKFX_DIVIDE => 2,
CLKFX_MULTIPLY => 8, -- 8 FOR 200 MHz
CLKIN_DIVIDE_BY_2 => FALSE,
CLKIN_PERIOD => 20.0,
CLKOUT_PHASE_SHIFT => "NONE",
CLK_FEEDBACK => "1X",
DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS",
DFS_FREQUENCY_MODE => "LOW",
DLL_FREQUENCY_MODE => "LOW",
DUTY_CYCLE_CORRECTION => TRUE,
FACTORY_JF => X"C080",
PHASE_SHIFT => 0,
STARTUP_WAIT => FALSE)
port map (
CLK0 => clk0_0, --
CLKFB => clk0_0, -- DCM clock feedback
CLKFX => clkfx0,
CLKIN => CLK, -- Clock input (from IBUFG, BUFG or DCM)
PSCLK => '0', -- Dynamic phase adjust clock input
PSEN => '0', -- Dynamic phase adjust enable input
PSINCDEC => '0', -- Dynamic phase adjust increment/decrement
RST => '0' -- DCM asynchronous reset input
);
BUFG_inst0 : BUFG
port map (
O => fclk, -- Clock buffer output
I => clkfx0 -- Clock buffer input
);
ClockMultM : DCM
generic map (
CLKDV_DIVIDE => 2.0,
CLKFX_DIVIDE => 2,
CLKFX_MULTIPLY => 4, -- 4 FOR 100 MHz
CLKIN_DIVIDE_BY_2 => FALSE,
CLKIN_PERIOD => 20.0,
CLKOUT_PHASE_SHIFT => "NONE",
CLK_FEEDBACK => "1X",
DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS",
DFS_FREQUENCY_MODE => "LOW",
DLL_FREQUENCY_MODE => "LOW",
DUTY_CYCLE_CORRECTION => TRUE,
FACTORY_JF => X"C080",
PHASE_SHIFT => 0,
STARTUP_WAIT => FALSE)
port map (
CLK0 => clk0_1, --
CLKFB => clk0_1, -- DCM clock feedback
CLKFX => clkfx1,
CLKIN => CLK, -- Clock input (from IBUFG, BUFG or DCM)
PSCLK => '0', -- Dynamic phase adjust clock input
PSEN => '0', -- Dynamic phase adjust enable input
PSINCDEC => '0', -- Dynamic phase adjust increment/decrement
RST => '0' -- DCM asynchronous reset input
);
BUFG_inst1 : BUFG
port map (
O => clklow, -- Clock buffer output
I => clkfx1 -- Clock buffer input
);
-- End of DCM_inst instantiation
ICAP_SPARTAN6_inst : ICAP_SPARTAN6
generic map (
DEVICE_ID => X"2000093", -- Specifies the pre-programmed Device ID value
SIM_CFG_FILE_NAME => "NONE" -- Specifies the Raw Bitstream (RBT) file to be parsed by the simulation
-- model
)
port map (
-- BUSY => BUSY, -- 1-bit output: Busy/Ready output
-- O => ICapO, -- 16-bit output: Configuration data output bus
CE => '0', -- 1-bit input: Active-Low ICAP Enable input
CLK => ICapClock, -- 1-bit input: Clock input
I => ICapI, -- 16-bit input: Configuration data input bus
WRITE => '0' -- 1-bit input: Read/Write control input
);
gcspi: process(clklow,COM_SPICLK) -- SPI interface with separate GClk SPI clock CPOL 0 CPHA 0
begin
if Rising_edge(COM_SPICLK) then -- sample the SPI data in on rising edge
if UpdateSPIReg = '1' then
UpdateSPIReg <= '0';
end if;
if COM_SPICS= '0' then
SPIRegIn <= SPIRegIN(30 downto 0) & COM_SPIIn; -- shift left (MSB first)
SPIBitCount <= SPIBitCount +1;
if SPIHeader= '1' then
if SPIBitCount = "01000" then -- clear command etc at 8
AddrPtr <= x"0000";
SPICommand <= "0000";
SPIBurstCount <= "0000000";
SPIAutoInc <= '0';
end if;
if SPIBitCount = "10000" then
AddrPtr <= SPIRegIn(15 downto 0); -- grab address on the fly at 16
end if;
if SPIBitCount = "10100" then
SPICommand <= SPIRegIn(3 downto 0); -- grab command on the fly at 20
end if;
if SPIBitCount = "10101" then
SPIAutoInc <= SPIRegIn(0); -- grab autoinc on the fly at 21
SPIHeaderFlag <= '1'; -- signal HM2 clock domain process
end if;
if SPIBitCount = "11100" then -- grab burst count at 28
SPIBurstCount <= SPIRegIn(6 downto 0);
end if;
if SPIBitCount = "11111" then
SPIHeader <= '0';
end if;
else -- not header
if SPIBitCount = "11111" then
if SPIBurstCount = 1 then
SPIHeader <= '1';
else
SPIBurstCount <= SPIBurstCount -1;
end if;
end if;
end if; --header
if (SPICommand = SPIRead) and (SPIBitCount = "10110") and (SPIBurstCount /= 1) then -- read request at bit 22
SPIReadRequest <= '1';
UpdateSPIReg <= '1';
end if;
end if; -- CS = 0
end if; -- clk rising edge
if Falling_edge(COM_SPICLK) then -- shift data out on falling edge
if COM_SPICS = '0' then
if (SPICommand = SPIWrite) and (SPIBitCount = "10110") and SPIHeader = '0' then -- write request at bit 22
NeedWrite <= '1';
end if;
if NeedWrite = '1' and SPIBitCount = "00000" then
SPIWriteRequest <= '1';
HM2DataInL <= SPIRegIn;
NeedWrite <= '0';
end if;
if UpDateSPIReg = '1' then
UpDateSPIRegD <= '1';
end if;
SPIRegOut <= SPIRegOut(30 downto 0) & '0';
if SPIBitCount = "00000" and UpdateSPIRegD = '1' then
SPIRegOut <= HM2DataOutL;
UpdateSPIRegD <= '0';
end if;
end if;
end if;
if rising_edge(ClkLow) then
SPIReadRequest2 <= SPIReadRequest1;
SPIWriteRequest2 <= SPIWriteRequest1;
SPIHeaderFlag2 <= SPIHeaderFlag1;
SPIReadRequest1 <= SPIReadRequest;
SPIWriteRequest1 <= SPIWriteRequest;
SPIHeaderFlag1 <= SPIHeaderFlag;
FrameTimerMSBD <= FrameTimerMSB;
DCOM_SPICS <= COM_SPICS;
if DCOM_SPICS = '1' then
if FrameTimerMSB = '0' then
FrameTimer <= FrameTimer -1;
end if;
else
FrameTimer <= SPITimeout;
end if;
if Read32 = '1' then
HM2DataOutL <= HM2DataOut;
if SPIAutoInc = '1' then
SyncAddrPtr <= SyncAddrPtr +4;
end if;
end if;
Write32Pipe <= Write32Pipe(2 downto 0) & (SPIWriteRequest1 and SPIWriteRequest2) ;
if Write32 = '1' then
if SPIAutoInc = '1' then
SyncAddrPtr <= SyncAddrPtr +4;
end if;
end if;
if (SPIHeaderFlag1 = '1') and (SPIHeaderFlag2 = '1') then
SyncAddrPtr <= AddrPtr;
end if;
end if; -- clock low
if (FrameTimerMSB = '1') and (FrameTimerMSBD = '0') then -- always set header on frame timeout
SPIHeader <= '1'; -- async set header
SPIRegOut <= x"AAAAAAAA";
end if;
if (SPIReadRequest1 = '1') and (SPIReadRequest2 = '1') then
SPIReadRequest <= '0'; -- async clear request
Read32 <= '1';
else
Read32 <= '0';
end if;
if (SPIWriteRequest1 = '1') and (SPIWriteRequest2 = '1') then
SPIWriteRequest <= '0'; -- async clear request
end if;
if (SPIHeaderFlag1 = '1') and (SPIHeaderFlag2 = '1') then
SPIHeaderFlag <= '0'; -- async clear request
end if;
if COM_SPICS = '1' then -- need filter!
SPIBitCount <= "00000"; -- async clear bit count
end if;
COM_SPIOUT <= SPIRegOut(31);
TEST0 <= SPIReadRequest;
end process;
ConfigDecode : process(AddrPtr,Read32,Write32)
begin
LoadSPICS <= decodedstrobe(AddrPtr(AddrWidth-1 downto 2)&"00",x"0070",Write32);
ReadSPICS <= decodedstrobe(AddrPtr(AddrWidth-1 downto 2)&"00",x"0070",Read32);
LoadSPIReg <= decodedstrobe(AddrPtr(AddrWidth-1 downto 2)&"00",x"0074",Write32);
ReadSPIReg <= decodedstrobe(AddrPtr(AddrWidth-1 downto 2)&"00",x"0074",Read32);
end process ConfigDecode;
doreconfig: process (clklow,ReConfigreg, AddrPtr)
begin
if AddrPtr = x"7F7F" then
ReconfigSel <= '1';
else
ReconfigSel <= '0';
end if;
if rising_edge(clklow) then
if Write32 = '1' and ReconfigSel = '1' then
if HM2DataInL(7 downto 0) = x"5A" then
ReConfigReg <= '1';
end if;
end if;
end if;
RECONFIG <= not ReConfigReg;
end process doreconfig;
asimplspi: entity work.simplespi8 -- configuration serial EEPROM access SPI port
generic map
(
buswidth => 8,
div => 7, -- for divide by 8 -- 12.5 MHz
bits => 8
)
port map
(
clk => clklow,
ibus => HM2DataInL(7 downto 0),
obus => HM2DataOut(7 Downto 0),
loaddata => LoadSPIReg,
readdata => ReadSPIReg,
loadcs => LoadSPICS,
readcs => ReadSPICS,
spiclk => SPICLK,
spiin => SPIIN,
spiout => SPIOUT,
spics =>SPICS
);
ICapDecode : process(Addrptr,Write32)
begin
LoadICap <= decodedstrobe(AddrPtr(AddrWidth-1 downto 2)&"00",x"0078",Write32);
ReadICapCookie <= decodedstrobe(AddrPtr(AddrWidth-1 downto 2)&"00",x"0078",Read32);
end process ICAPDecode;
ICapSupport: process (clklow,LoadICap)
begin
if rising_edge(clklow) then
if LoadICap = '1' then
ICapI <= FixICap(HM2DataInL(15 downto 0));
ICapTimer <= "111111";
end if;
if ICapTimer /= "000000" then
ICapTimer <= ICapTimer -1;
end if;
ICapClock <= ((not ICapTImer(5)) and ICapTimer(4)); -- 16 counts wide , 32 counts late
end if;
HM2DataOut <= (others => 'Z');
if ReadICAPCookie = '1' then
HM2DataOut <= x"1CAB1CAB";
end if;
end process ICapSupport;
dofallback: if fallback generate -- do blinky red light to indicate failure to load primary bitfile
Fallbackmode : process(clklow)
begin
if rising_edge(clklow) then
blinkcount <= blinkcount +1;
end if;
NINIT <= blinkcount(25);
end process;
end generate;
donormal: if not fallback generate
NormalMode : process(clklow)
begin
NINIT <= 'Z';
end process;
end generate;
end;