library IEEE;
use IEEE.std_logic_1164.all; -- defines std_logic types
use IEEE.std_logic_ARITH.ALL;
use IEEE.std_logic_UNSIGNED.ALL;
entity Main is
port
(
-- bus interface signals --
LRD: in std_logic;
LWR: in std_logic;
LW_R: in std_logic;
ALE: in std_logic;
ADS: in std_logic;
BLAST: in std_logic;
WAITO: in std_logic;
LOCKO: in std_logic;
CS0: in std_logic;
CS1: in std_logic;
READY: out std_logic;
INT: out std_logic;
LAD: inout std_logic_vector (31 downto 0); -- data/address bus
LA: in std_logic_vector (8 downto 2); -- non-muxed address bus
lBE: in std_logic_vector (3 downto 0); -- byte enables
IOBits: inout std_logic_vector (71 downto 0);
SYNCLK: in std_logic;
LCLK: in std_logic;
-- led bits
LEDS: out std_logic_vector(7 downto 0)
);
end Main;
architecture dataflow of Main is
constant StepGens: integer := 8;
constant QCounters: integer := 8;
constant PWMGens: integer := 8;
constant PortWidth: integer := 24;
constant BusWidth: integer := 32;
alias BLE: std_logic is LBE(0); -- 16 bit mode
alias BHE: std_logic is LBE(3); -- 16 bit mode
alias LA1: std_logic is LBE(1); -- 8/16 bit mode
alias LA0: std_logic is LBE(0); -- 8 bit mode
-- misc global signals --
signal D: std_logic_vector (BusWidth-1 downto 0); -- internal data bus
signal A: std_logic_vector (15 downto 2);
signal Read: std_logic;
signal Write: std_logic;
signal Burst: std_logic;
signal BurstCount: std_logic_vector (7 downto 0);
signal NextA: std_logic_vector (15 downto 2);
signal ArmBurstCounter: std_logic;
signal test32: std_logic_vector (BusWidth-1 downto 0);
-- decodes --
-- IDROM related signals
signal LoadIDROM: std_logic;
signal ReadIDROM: std_logic;
signal LoadIDROMWEn: std_logic;
signal ReadIDROMWEn: std_logic;
signal IDROMWEn: std_logic_vector(0 downto 0);
signal ROMAdd: std_logic_vector(7 downto 0);
-- I/O port related signals
signal PortSel: std_logic;
signal LoadPortCmd: std_logic_vector(3 downto 0);
signal ReadPortCmd: std_logic_vector(3 downto 0);
signal DDRSel: std_logic;
signal LoadDDRCmd: std_logic_vector(3 downto 0);
signal ReadDDRCmd: std_logic_vector(3 downto 0);
-- Step generator related signals
signal StepGenRateSel: std_logic;
signal LoadStepGenRate: std_logic_vector(StepGens -1 downto 0);
signal ReadStepGenRate: std_logic_vector(StepGens -1 downto 0);
signal StepGenAccumSel: std_logic;
signal LoadStepGenAccum: std_logic_vector(StepGens -1 downto 0);
signal ReadStepGenAccum: std_logic_vector(StepGens -1 downto 0);
signal StepGenModeSel: std_logic;
signal LoadStepGenMode: std_logic_vector(StepGens -1 downto 0);
signal ReadStepGenMode: std_logic_vector(StepGens -1 downto 0);
signal StepGenDSUTimeSel: std_logic;
signal LoadStepGenDSUTime: std_logic_vector(StepGens -1 downto 0);
signal ReadStepGenDSUTime: std_logic_vector(StepGens -1 downto 0);
signal StepGenDHLDTimeSel: std_logic;
signal LoadStepGenDHLDTime: std_logic_vector(StepGens -1 downto 0);
signal ReadStepGenDHLDTime: std_logic_vector(StepGens -1 downto 0);
signal StepGenPulseWidthSel: std_logic;
signal LoadStepGenPulseWidth: std_logic_vector(StepGens -1 downto 0);
signal ReadStepGenPulseWidth: std_logic_vector(StepGens -1 downto 0);
-- Step generators master rate related signals
signal LoadStepGenBasicRate: std_logic;
signal ReadStepGenBasicRate: std_logic;
signal StepGenBasicRate: std_logic;
-- Quadrature counter related signals
signal QCounterSel : std_logic;
signal LoadQCounter: std_logic_vector(QCounters -1 downto 0);
signal ReadQCounter: std_logic_vector(QCounters -1 downto 0);
signal QCounterCCRSel : std_logic;
signal LoadQCounterCCR: std_logic_vector(QCounters -1 downto 0);
signal ReadQCounterCCR: std_logic_vector(QCounters -1 downto 0);
-- Quadrature counter timestamp reference counter
signal LoadTSDiv : std_logic;
signal ReadTSDiv : std_logic;
signal ReadTS : std_logic;
signal TimeStampBus: std_logic_vector(15 downto 0);
function OneOffourdecode(ena1 : std_logic;ena2 : std_logic; dec : std_logic_vector(1 downto 0)) return std_logic_vector is
variable result : std_logic_vector(3 downto 0);
begin
if ena1 = '1' and ena2 = '1' then
case dec is
when "00" => result := "0001";
when "01" => result := "0010";
when "10" => result := "0100";
when "11" => result := "1000";
when others => result := "0000";
end case;
else
result := "0000";
end if;
return result;
end OneOfFourDecode;
function OneOfEightdecode(ena1 : std_logic;ena2 : std_logic; dec : std_logic_vector(2 downto 0)) return std_logic_vector is
variable result : std_logic_vector(7 downto 0);
begin
if ena1 = '1' and ena2 = '1' then
case dec is
when "000" => result := "00000001";
when "001" => result := "00000010";
when "010" => result := "00000100";
when "011" => result := "00001000";
when "100" => result := "00010000";
when "101" => result := "00100000";
when "110" => result := "01000000";
when "111" => result := "10000000";
when others => result := "00000000";
end case;
else
result := "00000000";
end if;
return result;
end OneOfEightDecode;
function OneOfTwelvedecode(ena1 : std_logic;ena2 : std_logic; dec : std_logic_vector(3 downto 0)) return std_logic_vector is
variable result : std_logic_vector(11 downto 0);
begin
if ena1 = '1' and ena2 = '1' then
case dec is
when "0000" => result := "000000000001";
when "0001" => result := "000000000010";
when "0010" => result := "000000000100";
when "0011" => result := "000000001000";
when "0100" => result := "000000010000";
when "0101" => result := "000000100000";
when "0110" => result := "000001000000";
when "0111" => result := "000010000000";
when "1000" => result := "000100000000";
when "1001" => result := "001000000000";
when "1010" => result := "010000000000";
when "1011" => result := "100000000000";
when others => result := "000000000000";
end case;
else
result := "000000000000";
end if;
return result;
end OneOftwelveDecode;
-- components --
component boutreg is
generic ( size : integer );
Port (
clk : in std_logic;
ibus : in std_logic_vector(BusWidth-1 downto 0);
obus : out std_logic_vector(BusWidth-1 downto 0);
load : in std_logic;
read : in std_logic;
dout : out std_logic_vector(size -1 downto 0));
end component boutreg;
component WordPR is
generic(size : integer);
port (
clear: in std_logic;
clk: in std_logic;
ibus: in std_logic_vector (BusWidth-1 downto 0);
obus: out std_logic_vector (BusWidth -1 downto 0);
loadport: in std_logic;
loadddr: in std_logic;
readddr: in std_logic;
portdata: out std_logic_vector (PortWidth -1 downto 0)
);
end component WordPR;
component WordRB is
generic(size : integer);
port (
obus: out std_logic_vector (BusWidth -1 downto 0);
readport: in std_logic;
portdata: in std_logic_vector (PortWidth -1 downto 0) );
end component WordRB;
component rategen is
port (
ibus : in std_logic_vector(BusWidth -1downto 0);
obus : out std_logic_vector(BusWidth -1 downto 0);
loadbasicrate : in std_logic;
readbasicrate : in std_logic;
hold : in std_logic;
basicrate : out std_logic;
clk : in std_logic);
end component rategen;
component stepgen is
port (
clk : in std_logic;
ibus : in std_logic_vector(BusWidth -1 downto 0);
obus : out std_logic_vector(BusWidth -1 downto 0);
loadsteprate : in std_logic;
loadaccum : in std_logic;
loadstepmode : in std_logic;
loaddirsetuptime : in std_logic;
loaddirholdtime : in std_logic;
loadpulsewidth : in std_logic;
readsteprate : in std_logic;
readaccum : in std_logic;
readstepmode : in std_logic;
readdirsetuptime : in std_logic;
readdirholdtime : in std_logic;
readpulsewidth : in std_logic;
basicrate : in std_logic;
hold : in std_logic;
outa : out std_logic;
outb : out std_logic
);
end component stepgen;
component qcounter is
port (
obus: out std_logic_vector (31 downto 0);
ibus: in std_logic_vector (31 downto 0);
quada: in std_logic;
quadb: in std_logic;
index: in std_logic;
loadccr: in std_logic;
readccr: in std_logic;
readcount: in std_logic;
countclear: in std_logic;
timestamp: in std_logic_vector (15 downto 0);
indexmask: in std_logic;
clk: in std_logic
);
end component qcounter;
component timestamp is
port (
ibus : in std_logic_vector(15 downto 0);
obus : out std_logic_vector(15 downto 0);
loadtsdiv : in std_logic;
readts : in std_logic;
readtsdiv : in std_logic;
tscount : out std_logic_vector (15 downto 0);
clk : in std_logic);
end component timestamp;
component maskmerge is
generic ( channels : integer; inputpol: std_logic );
port ( ibus : in std_logic_vector(BusWidth -1 downto 0);
obus : out std_logic_vector(BusWidth -1 downto 0);
loadmask : in std_logic;
readmask : in std_logic;
readstatus : in std_logic;
sin : in std_logic_vector(channels-1 downto 0);
clk : in std_logic;
sout : out std_logic);
end component maskmerge;
component spblockram256x32 is
port (
clk : in std_logic;
we : in std_logic;
re : in std_logic;
add : in std_logic_vector(7 downto 0);
din : in std_logic_vector(31 downto 0);
dout : out std_logic_vector(31 downto 0));
end component spblockram256x32;
begin
makeoports: for i in 0 to 2 generate
oportx: WordPR
generic map (size => PortWidth)
port map (
clear => '0',
clk => LClk,
ibus => LAD,
obus => D,
loadport => LoadPortCmd(i),
loadddr => LoadDDRCmd(i),
readddr => ReadDDRCmd(i),
portdata => IOBits((((i+1)*PortWidth) -1) downto (i*PortWidth))
);
end generate;
makeiports: for i in 0 to 2 generate
iportx: WordRB
generic map (size => PortWidth)
port map (
obus => D,
readport => ReadPortCmd(i),
portdata => IOBits((((i+1)*PortWidth) -1) downto (i*PortWidth))
);
end generate;
StepRategen : RateGen port map(
ibus => LAD,
obus => D,
loadbasicrate => LoadStepGenBasicRate,
readbasicrate => ReadStepGenBasicRate,
hold => '0',
basicrate => StepGenBasicRate,
clk => LClk);
makestepgens: for i in 0 to StepGens-1 generate
stepgenx: stepgen port map (
clk => LClk,
ibus => LAD,
obus => D,
loadsteprate => LoadStepGenRate(i),
loadaccum => LoadStepGenAccum(i),
loadstepmode => LoadStepGenMode(i),
loaddirsetuptime => LoadStepGenDSUTime(i),
loaddirholdtime => LoadStepGenDHLDTime(i),
loadpulsewidth => LoadStepGenPulseWidth(i),
readsteprate => ReadStepGenRate(i),
readaccum => ReadStepGenAccum(i),
readstepmode => ReadStepGenMode(i),
readdirsetuptime => ReadStepGenDSUTime(i),
readdirholdtime => ReadStepGenDHLDTime(i),
readpulsewidth => ReadStepGenPulseWidth(i),
basicrate => StepGenBasicRate,
hold => '0',
outa => IOBits(2*i), -- densely packed starting with I/O bit 0
outb => IOBits(2*i+1)
);
end generate;
makequadcounters: for i in 0 to QCounters-1 generate
qcounterx: qcounter port map (
obus => D,
ibus => LAD,
quada => IOBits(24 +3*i),
quadb => IOBits(25 +3*i),
index => IOBits(26 +3*i),
loadccr => LoadQcounterCCR(i),
readccr => ReadQcounterCCR(i),
readcount => ReadQcounter(i),
countclear => LoadQcounter(i),
timestamp => TimeStampBus,
indexmask => IOBits(48 + i),
clk => LCLK
);
end generate;
timestampx: timestamp port map(
ibus => LAD(15 downto 0),
obus => D(15 downto 0),
loadtsdiv => LoadTSDiv ,
readts => ReadTS,
readtsdiv =>ReadTSDiv,
tscount => TimeStampBus,
clk => LCLK
);
IDROM : spblockram256x32
port map (
clk => LCLK,
we => LoadIDROM,
re => ReadIDROM,
add => ROMAdd,
din => LAD,
dout => D
);
IDROMWP : boutreg
generic map (size => 1)
port map (
clk => LCLK,
ibus => LAD,
obus => D,
load => LoadIDROMWEn,
read => ReadIDROMWEn,
dout => IDROMWen
);
LooseEnds: process(A)
begin
INT <= '1';
READY <= '0';
if LW_R = '1' then
ROMAdd <= A(9 downto 2); -- on a write we use the delayed address
else
ROMAdd <= NextA(9 downto 2); -- on a read we use the undelayed address
end if;
end process;
Decode: process(A)
begin
-- basic multi decodes are at 256 byte increments (64 longs)
-- first decode is 256 x 32 ID ROM
if (A(15 downto 10) = "000000") and Write = '1' and IDROMWEn = "1" then --
LoadIDROM <= '1';
else
LoadIDROM <= '0';
end if;
if (A(15 downto 10) = "000000") and Read = '1' then --
ReadIDROM <= '1';
else
ReadIDROM <= '0';
end if;
if A(15 downto 8) = x"10" then -- basic I/O port select
PortSel <= '1';
else
PortSel <= '0';
end if;
if A(15 downto 8) = x"11" then -- DDR register select
DDRSel <= '1';
else
DDRSel <= '0';
end if;
if A(15 downto 8) = x"20" then -- stepgen rate register select
StepGenRateSel <= '1';
else
StepGenRateSel <= '0';
end if;
if A(15 downto 8) = x"21" then -- stepgen Accumumlator low select
StepGenAccumSel <= '1';
else
StepGenAccumSel <= '0';
end if;
if A(15 downto 8) = x"22" then -- stepgen mode register select
StepGenModeSel <= '1';
else
StepGenModeSel <= '0';
end if;
if A(15 downto 8) = x"23" then -- stepgen Dir setup time register select
StepGenDSUTimeSel <= '1';
else
StepGenDSUTimeSel <= '0';
end if;
if A(15 downto 8) = x"24" then -- stepgen Dir hold time register select
StepGenDHLDTimeSel <= '1';
else
StepGenDHLDTimeSel <= '0';
end if;
if A(15 downto 8) = x"25" then -- stepgen pulse width register select
StepGenPulseWidthSel <= '1';
else
StepGenPulseWidthSel <= '0';
end if;
if A(15 downto 8) = x"30" then -- QCounter select
QCounterSel <= '1';
else
QCounterSel <= '0';
end if;
if A(15 downto 8) = x"31" then -- QCounter CCR register select
QCounterCCRSel <= '1';
else
QCounterCCRSel <= '0';
end if;
-- basic single decodes are at 16 byte increments (4 longs)
-- these are mainly for common control logic
if A(15 downto 4) = x"C00" and Write = '1' then --
LoadStepGenBasicRate <= '1';
else
LoadStepGenBasicRate <= '0';
end if;
if A(15 downto 4) = x"C00" and Read = '1' then --
ReadStepGenBasicRate <= '1';
else
ReadStepGenBasicRate <= '0';
end if;
if A(15 downto 4) = x"C10" and Write = '1' then --
LoadTSDiv <= '1';
else
LoadTSDiv <= '0';
end if;
if A(15 downto 4) = x"C10" and Read = '1' then --
ReadTSDiv <= '1';
else
ReadTSDiv <= '0';
end if;
if A(15 downto 4) = x"C20" and Read = '1' then --
ReadTS <= '1';
else
ReadTS <= '0';
end if;
if A(15 downto 4) = x"CC0" and Write = '1' then --
LoadIDROMWEn <= '1';
else
LoadIDROMWEn <= '0';
end if;
if A(15 downto 4) = x"CC0" and Read = '1' then --
ReadIDROMWEn<= '1';
else
ReadIDROMWEn <= '0';
end if;
end process;
PortDecode: process (A,Read,Write)
begin
LoadPortCMD <= OneOfFourDecode(PortSel,Write,A(3 downto 2));
ReadPortCMD <= OneOfFourDecode(PortSel,Read,A(3 downto 2));
LoadDDRCMD <= OneOfFourDecode(DDRSel,Write,A(3 downto 2));
ReadDDRCMD <= OneOfFourDecode(DDRSel,Read,A(3 downto 2));
LoadStepGenRate <= OneOfEightdecode(StepGenRateSel,Write,A(4 downto 2));
ReadStepGenRate <= OneOfEightdecode(StepGenRateSel,Read,A(4 downto 2));
LoadStepGenAccum <= OneOfEightdecode(StepGenAccumSel,Write,A(4 downto 2));
ReadStepGenAccum <= OneOfEightdecode(StepGenAccumSel,Read,A(4 downto 2));
LoadStepGenMode <= OneOfEightdecode(StepGenModeSel,Write,A(4 downto 2));
ReadStepGenMode <= OneOfEightdecode(StepGenModeSel,Read,A(4 downto 2));
LoadStepGenDSUTime <= OneOfEightdecode(StepGenDSUTimeSel,Write,A(4 downto 2));
ReadStepGenDSUTime <= OneOfEightdecode(StepGenDSUTimeSel,Read,A(4 downto 2));
LoadStepGenDHLDTime <= OneOfEightdecode(StepGenDHLDTimeSel,Write,A(4 downto 2));
ReadStepGenDHLDTime <= OneOfEightdecode(StepGenDHLDTimeSel,Read,A(4 downto 2));
LoadStepGenPulseWidth <= OneOfEightdecode(StepGenPulseWidthSel,Write,A(4 downto 2));
ReadStepGenPulseWidth <= OneOfEightdecode(StepGenPulseWidthSel,Read,A(4 downto 2));
LoadQCounter <= OneOfEightdecode(QCounterSel,Write,A(4 downto 2));
ReadQCounter <= OneOfEightdecode(QCounterSel,Read,A(4 downto 2));
LoadQCounterCCR <= OneOfEightdecode(QCounterCCRSel,Write,A(4 downto 2));
ReadQCounterCCR <= OneOfEightdecode(QCounterCCRSel,Read,A(4 downto 2));
end process PortDecode;
LADDrivers: process (D,Read)
begin
if Read ='1' then
LAD <= D;
else
LAD <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
end if;
end process LADDrivers;
BusCycleGen: process (LCLK)
begin
if LCLK'event and LCLK = '1' then
A <= NextA; -- always update our latched address
if ADS = '0' then -- if *ADS then latch address & indicate start of burst
Burst <= '1';
-- if ArmBurstCounter = '1' then
-- BurstCount <= x"00"; -- BurstCount is just used for testing
-- end if;
end if;
-- if Burst = '1' then -- during burst, increment address
-- if ArmBurstCounter = '1' then
-- BurstCount <= BurstCount + 1;
-- end if;
-- end if;
if BLAST = '0' then -- end of burst
Burst <= '0';
-- ArmBurstCounter <= '0';
end if;
-- if LoadDDRCmd(3) = '1' then
-- ArmBurstCounter <= '1';
-- end if;
end if; -- lclk
if ADS = '0' then -- NextA is combinatorial next address
NextA <= LAD(15 downto 2); -- we need this for address lookahead for block RAM
else
NextA <= A+1;
end if;
Write <= Burst and LW_R; -- A write is any time during burst when LW_R is high
Read <= Burst and not LW_R; -- A read is any time during burst when LW_R is low
end process BusCycleGen;
-- TestLatch: process(lclk,ReadPortCmd)
-- begin
-- if lclk'event and LClk = '1' then
-- if LoadPortCmd(3) = '1' then
-- test32 <= LAD;
-- end if;
-- end if;
-- if ReadPortCmd(3) = '1' then
-- D <= test32;
-- else
-- D <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
-- end if;
-- end process;
ReadBurst: process(lclk,ReadDDRCmd)
begin
if ReadDDRCmd(3) = '1' then
D(7 downto 0) <= BurstCount;
D(31 downto 8) <= (others => '0');
else
D <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
end if;
end process;
end dataflow;