?
This commit is contained in:
444
5i24/configs/hostmot2/source/kubstepgenzid.vhd
Executable file
444
5i24/configs/hostmot2/source/kubstepgenzid.vhd
Executable file
@@ -0,0 +1,444 @@
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.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.
|
||||
--
|
||||
|
||||
|
||||
entity stepgenid is
|
||||
generic (
|
||||
buswidth : integer;
|
||||
timersize : integer;
|
||||
tablewidth : integer;
|
||||
asize : integer;
|
||||
rsize : integer;
|
||||
lsize : integer
|
||||
);
|
||||
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;
|
||||
loadpulseactivetime : in std_logic;
|
||||
loadpulseidletime : in std_logic;
|
||||
loadtable : in std_logic;
|
||||
loadtablemax : in std_logic;
|
||||
readsteprate : in std_logic;
|
||||
readaccum : in std_logic;
|
||||
readstepmode : in std_logic;
|
||||
readdirsetuptime : in std_logic;
|
||||
readdirholdtime : in std_logic;
|
||||
readpulseactivetime : in std_logic;
|
||||
readpulseidletime : in std_logic;
|
||||
readtable : in std_logic;
|
||||
readtablemax : in std_logic;
|
||||
basicrate : in std_logic;
|
||||
hold : in std_logic;
|
||||
index : in std_logic;
|
||||
probe : in std_logic;
|
||||
timer : in std_logic;
|
||||
timerenable : in std_logic;
|
||||
stout : out std_logic_vector(tablewidth-1 downto 0)
|
||||
);
|
||||
end stepgenid;
|
||||
|
||||
architecture Behavioral of stepgenid is
|
||||
|
||||
|
||||
-- Step Generator related signals
|
||||
|
||||
signal stepaccum: std_logic_vector(asize-1 downto 0);
|
||||
signal steplatch: std_logic_vector(buswidth-1 downto 0);
|
||||
signal nextaccum: std_logic_vector(asize-1 downto 0);
|
||||
alias stepmsbs: std_logic_vector(1 downto 0) is stepaccum(rsize-1 downto rsize -2);
|
||||
alias stepmsb: std_logic is stepaccum(rsize -1);
|
||||
alias nextmsb: std_logic is nextaccum(rsize -1);
|
||||
signal dstepmsb : std_logic;
|
||||
signal ddshold : std_logic;
|
||||
signal steprate: std_logic_vector(rsize -1 downto 0);
|
||||
alias stepdir: std_logic is steprate(rsize -1);
|
||||
signal dstepdir : std_logic;
|
||||
signal stepdirout : std_logic;
|
||||
signal pulsewait : std_logic;
|
||||
signal steppulse : std_logic := '0';
|
||||
signal dpulsewait : std_logic := '0';
|
||||
signal dirsetupwait : std_logic;
|
||||
signal dirholdwait : std_logic;
|
||||
signal dirshwait : std_logic;
|
||||
signal dirhold : std_logic;
|
||||
signal dirshcount: std_logic_vector(timersize-1 downto 0);
|
||||
signal pulsewidthcount: std_logic_vector(timersize-1 downto 0);
|
||||
signal dirsetuptime: std_logic_vector(timersize -1 downto 0);
|
||||
signal dirholdtime: std_logic_vector(timersize -1 downto 0);
|
||||
signal pulseactivetime: std_logic_vector(timersize -1 downto 0);
|
||||
signal pulseidletime: std_logic_vector(timersize -1 downto 0);
|
||||
signal stepmode: std_logic_vector(7 downto 0);
|
||||
signal localout: std_logic_vector(tablewidth-1 downto 0);
|
||||
signal wewouldcount : std_logic;
|
||||
signal dirchange : std_logic;
|
||||
signal waitforhold : std_logic;
|
||||
signal waitforpulse : std_logic;
|
||||
signal tableptr: std_logic_vector(3 downto 0);
|
||||
signal tablemax: std_logic_vector(3 downto 0);
|
||||
signal tabledata: std_logic_vector(tablewidth-1 downto 0);
|
||||
-- index and probe stuff;
|
||||
alias swapoutputs : std_logic is stepmode(2);
|
||||
alias latchonindex : std_logic is stepmode(4);
|
||||
alias indexpol : std_logic is stepmode(5);
|
||||
alias latchonprobe : std_logic is stepmode(6);
|
||||
alias probepol : std_logic is stepmode(7);
|
||||
signal indexflt: std_logic_vector(7 downto 0);
|
||||
signal probeflt: std_logic_vector(7 downto 0);
|
||||
signal indexd: std_logic_vector(1 downto 0);
|
||||
signal probed: std_logic_vector(1 downto 0);
|
||||
signal countlatch : std_logic_vector(lsize-1 downto 0);
|
||||
|
||||
signal dtimer : std_logic;
|
||||
signal sample : std_logic;
|
||||
|
||||
component SRL16E
|
||||
--
|
||||
generic (INIT : bit_vector);
|
||||
|
||||
|
||||
--
|
||||
port (D : in std_logic;
|
||||
CE : in std_logic;
|
||||
CLK : in std_logic;
|
||||
A0 : in std_logic;
|
||||
A1 : in std_logic;
|
||||
A2 : in std_logic;
|
||||
A3 : in std_logic;
|
||||
Q : out std_logic);
|
||||
end component;
|
||||
|
||||
|
||||
begin
|
||||
|
||||
steptable: for i in 0 to tablewidth -1 generate
|
||||
asr16e: SRL16E generic map (x"0000") port map(
|
||||
D => ibus(i),
|
||||
CE => loadtable,
|
||||
CLK => clk,
|
||||
A0 => tableptr(0),
|
||||
A1 => tableptr(1),
|
||||
A2 => tableptr(2),
|
||||
A3 => tableptr(3),
|
||||
Q => tabledata(i)
|
||||
);
|
||||
end generate;
|
||||
|
||||
astepgen: process (clk,stepdirout, steprate, nextaccum, stepaccum,dirshwait,
|
||||
dirholdwait, pulsewait, dpulsewait,dirchange,wewouldcount,waitforpulse,
|
||||
dirsetupwait, pulsewidthcount, dirshcount, dirhold, waitforhold,
|
||||
readaccum, tabledata, stepmode, steppulse, stepmsbs,localout)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
|
||||
if basicrate = '1' and hold = '0' and ddshold = '0' then -- our basic step rate DDS
|
||||
stepaccum <= nextaccum;
|
||||
dstepdir <= stepdir; -- only updated when we add
|
||||
end if;
|
||||
|
||||
if pulsewait = '1' then -- our two timers
|
||||
pulsewidthcount <= pulsewidthcount -1; -- we share dirshcount between setup and hold functions
|
||||
end if;
|
||||
|
||||
if (pulsewait = '0') and (dpulsewait = '1') and (steppulse = '1') then
|
||||
pulsewidthcount <= pulseidletime; -- output pulse idle time
|
||||
steppulse <= '0'; -- clear our output pulse
|
||||
end if;
|
||||
|
||||
if dirshwait = '1' then
|
||||
dirshcount <= dirshcount -1;
|
||||
end if;
|
||||
|
||||
if (stepmsb = '0' and dstepmsb = '1' and dstepdir = '0') -- overflow = we counted up
|
||||
or (stepmsb = '1' and dstepmsb = '0' and dstepdir = '1') then -- underflow = we counted down -- the output of the DDS
|
||||
pulsewidthcount <= pulseactivetime; -- output pulse active time
|
||||
steppulse <= '1';
|
||||
dirshcount <= dirholdtime; -- set pulse to dir change hold timer
|
||||
dirhold <= '1'; -- set our flag to indicate
|
||||
else
|
||||
if dirholdwait = '0' then -- no change during hold time
|
||||
if dirchange = '1' then -- we need to change the external direction signal
|
||||
dirshcount <= dirsetuptime; -- set dir change to next pulse setup time
|
||||
dirhold <= '0'; -- set our flag to indicate
|
||||
stepdirout <= stepdir; -- update the output direction
|
||||
end if; -- our timer is for setup time
|
||||
end if;
|
||||
end if; -- our timer is for hold time
|
||||
|
||||
|
||||
if (stepmsb = '0' and dstepmsb = '1' and dstepdir = '0') then -- we counted up
|
||||
if (tableptr = tablemax) then
|
||||
tableptr <= x"0";
|
||||
else
|
||||
tableptr <= tableptr +1;
|
||||
end if;
|
||||
end if;
|
||||
if (stepmsb = '1' and dstepmsb = '0' and dstepdir = '1') then -- we counted down
|
||||
if (tableptr = x"0") then
|
||||
tableptr <= tablemax;
|
||||
else
|
||||
tableptr <= tableptr -1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if loadstepmode = '1' then -- our register writes
|
||||
stepmode <= ibus(7 downto 0);
|
||||
end if;
|
||||
if loadsteprate = '1' then
|
||||
steprate <= ibus(rsize -1 downto 0);
|
||||
end if;
|
||||
if loadaccum = '1' then
|
||||
stepaccum(asize -1 downto asize-buswidth) <= ibus;
|
||||
dstepmsb <= ibus(buswidth-1); -- avoid generating a step when loading accumulator
|
||||
end if;
|
||||
if loaddirsetuptime = '1' then
|
||||
dirsetuptime <= ibus(timersize -1 downto 0);
|
||||
end if;
|
||||
if loaddirholdtime = '1' then
|
||||
dirholdtime <= ibus(timersize -1 downto 0);
|
||||
end if;
|
||||
if loadpulseactivetime = '1' then
|
||||
pulseactivetime <= ibus(timersize -1 downto 0);
|
||||
end if;
|
||||
if loadpulseidletime = '1' then
|
||||
pulseidletime <= ibus(timersize -1 downto 0);
|
||||
end if;
|
||||
|
||||
if loadtablemax = '1' then
|
||||
tablemax <= ibus(3 downto 0);
|
||||
tableptr <= x"0";
|
||||
end if;
|
||||
if sample = '1' then
|
||||
steplatch <= stepaccum(asize -1 downto asize-buswidth);
|
||||
end if;
|
||||
dpulsewait <= pulsewait;
|
||||
dstepmsb <= stepmsb;
|
||||
dtimer <= timer;
|
||||
-- index/probe logic
|
||||
|
||||
if index = '1' then
|
||||
if indexflt /= x"FF" then
|
||||
indexflt <= indexflt + 1;
|
||||
end if;
|
||||
else
|
||||
if indexflt /= x"0" then
|
||||
indexflt <= indexflt - 1;
|
||||
end if;
|
||||
end if;
|
||||
if indexflt = x"0" then
|
||||
indexd(0) <= '0';
|
||||
end if;
|
||||
if indexflt = x"FF" then
|
||||
indexd(0) <= '1';
|
||||
end if;
|
||||
indexd(1) <= indexd(0);
|
||||
|
||||
if probe = '1' then
|
||||
if probeflt /= x"FF" then
|
||||
probeflt <= probeflt + 1;
|
||||
end if;
|
||||
else
|
||||
if probeflt /= x"0" then
|
||||
probeflt <= probeflt - 1;
|
||||
end if;
|
||||
end if;
|
||||
if probeflt = x"0" then
|
||||
probed(0) <= '0';
|
||||
end if;
|
||||
if probeflt = x"FF" then
|
||||
probed(0) <= '1';
|
||||
end if;
|
||||
probed(1) <= probed(0);
|
||||
|
||||
if (indexd = "01" and latchonindex = '1' and indexpol = '1') or
|
||||
(indexd = "10" and latchonindex = '1' and indexpol = '0') then
|
||||
countlatch <= stepaccum(asize-1 downto asize-lsize);
|
||||
latchonindex <= '0';
|
||||
end if;
|
||||
|
||||
if (probed = "01" and latchonprobe = '1' and probepol = '1') or
|
||||
(probed = "10" and latchonprobe = '1' and probepol = '0') then
|
||||
countlatch <= stepaccum(asize-1 downto asize-lsize);
|
||||
latchonprobe <= '0';
|
||||
end if;
|
||||
|
||||
end if; -- clk
|
||||
|
||||
dirchange <= stepdirout xor stepdir;
|
||||
|
||||
if (stepmsb = '1' and nextmsb = '0' and stepdir = '0') -- overflow = we would count up
|
||||
or (stepmsb = '0' and nextmsb = '1' and stepdir = '1') then -- underflow = we would count down
|
||||
wewouldcount <= '1';
|
||||
else
|
||||
wewouldcount <= '0';
|
||||
end if;
|
||||
|
||||
waitforhold <= dirholdwait and dirchange;
|
||||
waitforpulse <= pulsewait or dpulsewait;
|
||||
|
||||
nextaccum <= signed(stepaccum)+ signed(steprate); -- to lookahead
|
||||
|
||||
if (wewouldcount = '1') and
|
||||
-- (((waitforhold = '1') or (dirsetupwait = '1') or (waitforpulse = '1'))) -- misses the case where Dirhold has timed out!
|
||||
(((waitforhold = '1') or (dirsetupwait = '1') or (waitforpulse = '1') or (dirchange = '1')))
|
||||
then -- need to pause
|
||||
ddshold <= '1';
|
||||
else
|
||||
ddshold <= '0';
|
||||
end if;
|
||||
|
||||
if pulsewidthcount = 0 then
|
||||
pulsewait <= '0';
|
||||
else
|
||||
pulsewait <= '1';
|
||||
end if;
|
||||
|
||||
if dirshcount = 0 then
|
||||
dirshwait <= '0';
|
||||
else
|
||||
dirshwait <= '1';
|
||||
end if;
|
||||
|
||||
dirholdwait <= (dirhold and dirshwait);
|
||||
dirsetupwait <= (not dirhold) and dirshwait;
|
||||
|
||||
if (timer = '1' and dtimer = '0') or (timerenable = '0') then -- rising edge of selected timer
|
||||
sample <= '1';
|
||||
else
|
||||
sample <= '0';
|
||||
end if;
|
||||
|
||||
obus <= (others => 'Z');
|
||||
|
||||
-- if readsteprate = '1' then
|
||||
-- obus(rsize -1 downto 0) <= steprate;
|
||||
-- end if;
|
||||
|
||||
if readaccum = '1' then
|
||||
obus <= steplatch;
|
||||
end if;
|
||||
|
||||
if readstepmode = '1' then
|
||||
obus(7 downto 0) <= stepmode;
|
||||
obus(buswidth-1 downto buswidth-lsize) <= countlatch;
|
||||
end if;
|
||||
|
||||
-- if readdirsetuptime = '1' then
|
||||
-- obus(timersize -1 downto 0) <= dirsetuptime; -- most register readbacks commented out for size
|
||||
-- obus(31 downto timersize) <= (others => '0');
|
||||
-- end if;
|
||||
-- if readdirholdtime = '1' then
|
||||
-- obus(timersize -1 downto 0) <= dirholdtime;
|
||||
-- obus(31 downto timersize) <= (others => '0');
|
||||
-- end if;
|
||||
-- if readpulseactivetime = '1' then
|
||||
-- obus(timersize -1 downto 0) <= pulsewidth;
|
||||
-- obus(31 downto timersize) <= (others => '0');
|
||||
-- end if;
|
||||
-- if readpulseidletime = '1' then
|
||||
-- obus(timersize -1 downto 0) <= pulseidle;
|
||||
-- obus(31 downto timersize) <= (others => '0');
|
||||
-- end if;
|
||||
|
||||
|
||||
localout <= tabledata; -- this is the default unless:
|
||||
case stepmode(1 downto 0) is
|
||||
when "00" =>
|
||||
localout(0) <= steppulse; -- step
|
||||
localOut(1) <= stepdirout; -- dir
|
||||
when "01" =>
|
||||
localout(0) <= steppulse and (not stepdirout); -- count up
|
||||
localOut(1) <= steppulse and stepdirout; -- count down
|
||||
when "10" =>
|
||||
case stepmsbs is
|
||||
when "00" => localout(1 downto 0) <= "00"; -- quadrature
|
||||
when "01" => localout(1 downto 0) <= "01";
|
||||
when "10" => localout (1 downto 0)<= "11";
|
||||
when "11" => localout(1 downto 0) <= "10";
|
||||
when others => null;
|
||||
end case;
|
||||
when others => null;
|
||||
end case;
|
||||
|
||||
if swapoutputs = '0' then
|
||||
stout <= localout;
|
||||
else
|
||||
stout(0) <= localout(1);
|
||||
stout(1) <= localout(0);
|
||||
end if;
|
||||
|
||||
end process astepgen;
|
||||
|
||||
end Behavioral;
|
||||
Reference in New Issue
Block a user