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

314 lines
9.9 KiB
VHDL
Executable File

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 oneshot is
port ( clk : in std_logic;
ibus : in std_logic_vector (31 downto 0);
obus : out std_logic_vector (31 downto 0);
loadpw1 : in std_logic;
loadpw2 : in std_logic;
loadfilter1 : in std_logic;
loadfilter2 : in std_logic;
loadrate : in std_logic;
loadcontrol : in std_logic;
readcontrol : in std_logic;
timers : in std_logic_vector(4 downto 0);
pulse1out : out std_logic;
pulse2out : out std_logic;
hwtrigger1 : in std_logic;
hwtrigger2 : in std_logic);
end oneshot;
architecture Behavioral of oneshot is
signal pw1: std_logic_vector(31 downto 0);
signal pw2: std_logic_vector(31 downto 0);
signal pw1count: std_logic_vector(32 downto 0);
signal pw2count: std_logic_vector(32 downto 0);
alias pw1countmsb: std_logic is pw1count(32);
alias pw2countmsb: std_logic is pw2count(32);
signal pw1prevmsb: std_logic;
signal pw2prevmsb: std_logic;
signal rateaccum: std_logic_vector(31 downto 0);
signal rateaccumreg: std_logic_vector(31 downto 0);
alias ratemsb: std_logic is rateaccum(31);
signal timerdiv: std_logic_vector(15 downto 0);
signal timerdivreg: std_logic_vector(15 downto 0);
signal trigfilterreg1: std_logic_vector(23 downto 0);
signal trigfilterreg2: std_logic_vector(23 downto 0);
signal trigfiltercount1: std_logic_vector(23 downto 0);
signal trigfiltercount2: std_logic_vector(23 downto 0);
signal trigger1: std_logic;
signal trigger2: std_logic;
signal triggerd1: std_logic;
signal triggerd2: std_logic;
signal exttrigger1: std_logic;
signal exttrigger2: std_logic;
signal dplltrigger: std_logic;
signal controlreg: std_logic_vector(31 downto 0);
signal hwtrigger1d: std_logic;
signal hwtrigger2d: std_logic;
signal run1: std_logic;
signal run2: std_logic;
alias startselect1: std_logic_vector(2 downto 0) is controlreg(2 downto 0);
alias startrise1: std_logic is controlreg(3);
alias startfall1: std_logic is controlreg(4);
alias retrigger1: std_logic is controlreg(5);
alias enable1: std_logic is controlreg(6);
alias reset1: std_logic is controlreg(7);
alias swtrigger1: std_logic is controlreg(10);
alias timerselect: std_logic_vector(3 downto 0) is controlreg(15 downto 12);
alias startselect2: std_logic_vector(2 downto 0) is controlreg(18 downto 16);
alias startrise2: std_logic is controlreg(19);
alias startfall2: std_logic is controlreg(20);
alias retrigger2: std_logic is controlreg(21);
alias enable2: std_logic is controlreg(22);
alias reset2: std_logic is controlreg(23);
alias swtrigger2: std_logic is controlreg(26);
begin
aoneshot: process (clk)
begin
if rising_edge(clk) then
triggerd1 <= trigger1;
triggerd2 <= trigger2;
hwtrigger1d <= hwtrigger1;
hwtrigger2d <= hwtrigger2;
if (hwtrigger1d = '1') and (trigfiltercount1 < trigfilterreg1) then
trigfiltercount1 <= trigfiltercount1 + 1;
end if;
if (hwtrigger1d = '0') and (trigfiltercount1 /= 0) then
trigfiltercount1 <= trigfiltercount1 -1;
end if;
if trigfiltercount1 >= trigfilterreg1 then
exttrigger1 <= '1';
-- trigfiltercount1 <= trigfilterreg1; -- handle the case where the filter time is reduced
end if;
if trigfiltercount1 = 0 then
exttrigger1 <= '0';
end if;
if (hwtrigger2d = '1') and (trigfiltercount2 < trigfilterreg2) then
trigfiltercount2 <= trigfiltercount2 + 1;
end if;
if (hwtrigger2d = '0') and (trigfiltercount2 /= 0) then
trigfiltercount2 <= trigfiltercount2 -1;
end if;
if trigfiltercount2 >= trigfilterreg2 then
exttrigger2 <= '1';
-- trigfiltercount2 <= trigfilterreg2; -- handle the case where the filter time is reduced
end if;
if trigfiltercount2 = 0 then
exttrigger2 <= '0';
end if;
rateaccum <= rateaccum + rateaccumreg;
case startselect1 is
when "000" => run1 <= '0'; -- cancel any pulse in progress
when "001" => trigger1 <= swtrigger1;
when "010" => trigger1 <= exttrigger1;
when "011" => trigger1 <= dplltrigger;
when "100" => trigger1 <= ratemsb;
when "101" => trigger1 <= run1;
when "110" => trigger1 <= run2;
when others => run1 <= '0';
end case;
case startselect2 is
when "000" => run2 <= '0'; -- cancel any pulse in progress
when "001" => trigger2 <= swtrigger2;
when "010" => trigger2 <= exttrigger2;
when "011" => trigger2 <= dplltrigger;
when "100" => trigger2 <= ratemsb;
when "101" => trigger2 <= run1;
when "110" => trigger2 <= run2;
when others => run2 <= '0';
end case;
if reset1 = '1' then
run1 <= '0';
end if;
if run1 = '1' then
if pw1countmsb = '0' then
pw1count <= pw1count -1;
end if;
end if;
if pw1countmsb = '1' then -- end of pulse
run1 <= '0';
end if;
if (run1 = '0') then
pw1count(31 downto 0) <= pw1;
pw1countmsb <='0';
end if;
if reset2 = '1' then
run2 <= '0';
end if;
if run2 = '1' then
if pw2countmsb = '0' then
pw2count <= pw2count -1;
end if;
end if;
if pw2countmsb = '1' then-- end of pulse
run2 <= '0';
end if;
if (run2 = '0') then
pw2count(31 downto 0) <= pw2;
pw2countmsb <='0';
end if;
if (startrise1 = '1' and trigger1 = '1' and triggerd1='0' and enable1='1')
or (startfall1 = '1' and trigger1 = '0' and triggerd1='1' and enable1='1') then
if retrigger1 = '1' then
run1 <= '1';
pw1count(31 downto 0) <= pw1; -- reload timer if retriggerable
pw1countmsb <='0';
else
if run1 = '0' then
run1 <= '1';
end if;
end if;
end if;
if (startrise2 = '1' and trigger2 = '1' and triggerd2='0' and enable2='1')
or (startfall2 = '1' and trigger2 = '0' and triggerd2='1' and enable2='1') then
if retrigger2 = '1' then
run2 <= '1';
pw2count(31 downto 0) <= pw2; -- reload timer if retriggerable
pw2countmsb <='0';
else
if run2 = '0' then
run2 <= '1';
end if;
end if;
end if;
if loadcontrol = '1' then
controlreg <= ibus(31 downto 0);
end if;
if loadpw1 = '1' then
pw1 <= ibus;
end if;
if loadpw2 = '1' then
pw2 <= ibus;
end if;
if loadfilter1 = '1' then
trigfilterreg1 <= ibus(23 downto 0);
end if;
if loadfilter2 = '1' then
trigfilterreg2 <= ibus(23 downto 0);
end if;
if loadrate = '1' then
rateaccumreg <= ibus;
end if;
end if; -- clk
case timerselect(2 downto 0) is
when "000" => dplltrigger <= timers(0);
when "001" => dplltrigger <= timers(1);
when "010" => dplltrigger <= timers(2);
when "011" => dplltrigger <= timers(3);
when "100" => dplltrigger <= timers(4);
when others => dplltrigger <= timers(0);
end case;
obus <= (others => 'Z');
if readcontrol = '1' then
obus(7 downto 0) <= controlreg(7 downto 0);
obus(8) <= run1;
obus(9) <= exttrigger1;
obus(10) <= swtrigger1;
obus(15 downto 12) <= timerselect;
obus(23 downto 16) <= controlreg(23 downto 16);
obus(24) <= run2;
obus(25) <= exttrigger2;
obus(26) <= swtrigger2;
obus(31 downto 27) <= (others => '0'); -- zero unused readback bits
obus(11) <= '0';
end if;
pulse1out <= run1;
pulse2out <= run2;
end process;
end Behavioral;