library IEEE; use IEEE.std_logic_1164.all; -- defines std_logic types use IEEE.std_logic_ARITH.ALL; use IEEE.std_logic_UNSIGNED.ALL; Library UNISIM; use UNISIM.vcomponents.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. -- use work.decodedstrobe.all; entity resolver is generic ( Clock : integer ); port ( clk : in std_logic; ibus : in std_logic_vector(31 downto 0); obus : out std_logic_vector(31 downto 0); hloadcommand : in std_logic; hreadcommand : in std_logic; hloaddata : in std_logic; hreaddata : in std_logic; hreadstatus : in std_logic; regaddr : in std_logic_vector(2 downto 0); readvel : in std_logic; -- for range 0..7 readpos: in std_logic;-- for range 0..7 testbit : out std_logic; respdmp : out std_logic; respdmm : out std_logic; spics : out std_logic; spiclk : out std_logic; spidi0 : in std_logic; spidi1 : in std_logic; pwren : out std_logic; chan0 : out std_logic; chan1 : out std_logic; chan2 : out std_logic ); end resolver; architecture dataflow of resolver is signal iabus: std_logic_vector(11 downto 0); signal idbus: std_logic_vector(23 downto 0); signal mradd: std_logic_vector(11 downto 0); signal mwadd: std_logic_vector(11 downto 0); signal mobus: std_logic_vector(31 downto 0); signal mwrite: std_logic; signal mread: std_logic; -- data memory partitioning-- signal muxedmibus: std_logic_vector(31 downto 0); -- the data input path to the processor signal ramdata: std_logic_vector(31 downto 0); -- and its sources signal sinedata: std_logic_vector(15 downto 0); signal iodata: std_logic_vector(31 downto 0); signal ioradd: std_logic_vector(11 downto 0); signal lloadvel: std_logic; signal writedram: std_logic; -- daq decode signals signal daqreadram: std_logic; signal daqloadmode: std_logic; signal daqreadptr: std_logic; signal daqclear: std_logic; signal startburst: std_logic; signal oldstartburst: std_logic; -- wavegen decode signals signal wgloadrate: std_logic; signal wgloadlength: std_logic; signal wgloadpdmrate: std_logic; signal wgloadtableptr: std_logic; signal wgloadtabledata: std_logic; -- host interface signals signal hcommandreg: std_logic_vector(15 downto 0); signal hdatareg: std_logic_vector(31 downto 0); alias romwrena : std_logic is hcommandreg(14); -- if high, reset CPU and allow read/write CPU ROM access signal lcommandreg: std_logic_vector(15 downto 0); signal lloadcommand: std_logic; signal lreadcommand: std_logic; signal ldatareg: std_logic_vector(31 downto 0); signal lloaddata: std_logic; signal lstatusreg: std_logic_vector(31 downto 0); signal lloadstatus: std_logic; signal lreaddata: std_logic; signal romdata: std_logic_vector(23 downto 0); signal loadrom: std_logic; signal velramdata: std_logic_vector(31 downto 0); signal hostreq: std_logic; signal lloadveli: std_logic; signal lloadintrate: std_logic; signal lreadpos: std_logic; -- our one bit pwr enable register signal lpwren: std_logic; signal loadpwren: std_logic; -- our logic for syncing processor to DAQ signal lreadccount: std_logic; signal ldeccount: std_logic; signal lcyclecount: std_logic_vector(7 downto 0); -- debug test bit out signal ltestbit: std_logic; signal lsettestbit: std_logic; signal lclrtestbit: std_logic; -- clock frequency read signal clockslv: std_logic_vector(31 downto 0); signal lreadclkfreq: std_logic; begin aproc: entity work.Big32v2 -- normally b32qcondmac2ws.vhd port map ( clk => clk, reset => romwrena, iabus => iabus, -- program address bus idbus => idbus, -- program data bus mradd => mradd, -- memory read address mwadd => mwadd, -- memory write address mibus => muxedmibus, -- memory data in bus mobus => mobus, -- memory data out bus mwrite => mwrite, -- memory write signal mread => mread -- memory read signal ); ResolverROM: entity work.resrom port map( addra => hcommandreg(9 downto 0), -- 1k (x24) till we run out of space addrb => iabus(9 downto 0), clk => clk, dina => ibus(23 downto 0), douta => romdata, doutb => idbus, wea => loadrom ); DataRam : entity work.dpram generic map ( width => 32, depth => 512 --256 ) port map( addra => mwadd(8 downto 0), --7 addrb => mradd(8 downto 0), --7 clk => clk, dina => mobus, -- douta => doutb => ramdata, wea => writedram ); SineTable : entity work.sine16 port map ( addr => mradd(9 downto 0), clk => clk, din => x"0000", dout => sinedata, we => '0' ); velram: entity work.dpram generic map ( width => 32, depth => 8 ) port map( addra => mwadd(2 downto 0), addrb => regaddr, clk => clk, dina => mobus, -- douta => doutb => velramdata, wea => lloadvel ); interfaceInteg : entity work.OutputInteg -- velocity --> position part of integrator (accumulator) -- is done in hardware so it can run faster than the sample rate (256 times here) -- so that the (asynchronous) host reads of position do not suffer -- major aliasing errors port map( dspdin => mobus, dspdout => iodata, hostdout => obus, dspraddr => mradd(2 downto 0), dspwaddr => mwadd(2 downto 0), hostaddr => regaddr, loadvel => lloadveli, loadrate => lloadintrate, dspread => lreadpos, hostread => readpos, -- testout => testbit, clk => clk ); ADAQ: entity work.resolverdaq2 -- A-D samples are written by SPI interface to dual ported RAM and read -- by DSP on other RAM port. Also handles DAQ rate and channel muxing port map ( clk => clk, ibus => mobus, obus => iodata, hostaddr => mradd(9 downto 0), ioradd0 => ioradd(0), readram => daqreadram, loadmode => daqloadmode, clear => daqclear, readstat => daqreadptr, startburst=> startburst, spiclk => spiclk, spiin0 => spidi0, spiin1 => spidi1, spiframe => spics, channelsel0 => chan0, channelsel1 => chan1, channelsel2 => chan2, testout => testbit ); AWavegen: entity work.syncwavegen port map( clk => clk , ibus => mobus, loadrate => wgloadrate, loadlength => wgloadlength, loadpdmrate => wgloadpdmrate, loadtableptr => wgloadtableptr, loadtabledata => wgloadtabledata, trigger1 => startburst, pdmouta => respdmp, pdmoutb => respdmm ); iobus: process(clk,ioradd,ramdata, iodata, sinedata) begin if rising_edge(clk) then ioradd <= mradd; end if; case ioradd(11 downto 10) is when "00" => muxedmibus <= ramdata; -- bottom 1K is RAM (only 512B now) when "01" => muxedmibus <= iodata; -- 1K is I/O space when "10" => muxedmibus(15 downto 0) <= sinedata; -- next 1K is 16 bit sine table muxedmibus(31 downto 16) <= (others => '0'); when "11" => muxedmibus <= iodata; -- top 1K is DAQ read data when others => null; end case; end process iobus; hostinterface : process (clk,lpwren, hloaddata, romwrena, hreadcommand, lcommandreg, hostreq, hreaddata, ldatareg, romdata, readvel, velramdata, lreadcommand, hcommandreg, lreaddata, hdatareg, lstatusreg, hreadstatus, lreadccount, lcyclecount) begin clockslv <= conv_std_logic_vector(Clock,32); -- first the writes if rising_edge(clk) then -- first host writes if hloadcommand = '1' then hcommandreg <= ibus(15 downto 0); hostreq <= '1'; end if; if hloaddata = '1' then hdatareg <= ibus; end if; -- next local writes and sync logic if lloadcommand = '1' then lcommandreg <= mobus(15 downto 0); hostreq <= '0'; end if; if lloaddata = '1' then ldatareg <= mobus; end if; if lloadstatus = '1' then lstatusreg <= mobus; end if; if loadpwren = '1' then lpwren <= mobus(0); end if; if oldstartburst = '0' and startburst = '1' then if ldeccount = '0' then lcyclecount <= lcyclecount +1; end if; else if ldeccount = '1' then lcyclecount <= lcyclecount -1; end if; end if; if lsettestbit = '1' then ltestbit <= '1'; end if; if lclrtestbit = '1' then ltestbit <= '0'; end if; oldstartburst <= startburst; -- testbit <= startburst; end if; -- clk pwren <= not lpwren; -- resolver drive power enable if hloaddata = '1' and romwrena = '1' then -- write data to rom on host datareg writes loadrom <= '1'; else loadrom <= '0'; end if; -- then the reads -- first the host reads obus <= (others => 'Z'); if hreadcommand = '1' then obus(15 downto 0) <= lcommandreg; obus(30 downto 16) <= (others => '0'); obus(31) <= hostreq; end if; if hreaddata = '1' then if romwrena = '0' then -- normally just read the local data register obus <= ldatareg; else obus(23 downto 0) <= romdata; -- but if romwrena set, read the ROM data obus(31 downto 24) <=(others => '0'); end if; end if; if hreadstatus = '1' then obus <= lstatusreg; end if; if readvel = '1' then obus <= velramdata; end if; -- then the local reads iodata <= (others => 'Z'); if lreadcommand = '1' then iodata(15 downto 0) <= hcommandreg; iodata(30 downto 16) <= (others => '0'); iodata(31) <= hostreq; end if; if lreaddata = '1' then iodata <= hdatareg; end if; if lreadccount = '1' then iodata(7 downto 0) <= lcyclecount; iodata(31 downto 8) <= (others => '0'); end if; if lreadclkfreq = '1' then iodata <= clockslv; end if; -- testbit <= ltestbit; end process hostinterface; localdecode : process (mradd,mwadd,ioradd,mwrite,mread) begin lloadcommand <= decodedstrobe(mwadd,x"400",mwrite); lreadcommand <= decodedstrobe(ioradd,x"400",mread); lloaddata <= decodedstrobe(mwadd,x"401",mwrite); lreaddata <= decodedstrobe(ioradd,x"401",mread); daqloadmode <= decodedstrobe(mwadd,x"402",mwrite); daqreadptr <= decodedstrobe(ioradd,x"402",mread); daqclear <= decodedstrobe(mwadd,x"403",mwrite); daqreadram <= decodedstrobe(ioradd(11 downto 10),"11",'1'); wgloadrate <= decodedstrobe(mwadd,x"404",mwrite); wgloadlength <= decodedstrobe(mwadd,x"405",mwrite); wgloadpdmrate <= decodedstrobe(mwadd,x"406",mwrite); wgloadtableptr <= decodedstrobe(mwadd,x"407",mwrite); wgloadtabledata <= decodedstrobe(mwadd,x"408",mwrite); loadpwren <= decodedstrobe(mwadd,x"409",mwrite); ldeccount <= decodedstrobe(mwadd,x"40A",mwrite); lreadccount <= decodedstrobe(ioradd,x"40A",mread); lsettestbit <= decodedstrobe(mwadd,x"40B",mwrite); lclrtestbit <= decodedstrobe(mwadd,x"40C",mwrite); lloadintrate <= decodedstrobe(mwadd,x"40D",mwrite); lloadstatus <= decodedstrobe(mwadd,x"40E",mwrite); lreadclkfreq <= decodedstrobe(ioradd,x"40F",mread); writedram <= decodedstrobe(mwadd(11 downto 10),"00",mwrite); lloadvel <= decodedstrobe(mwadd(11 downto 3),"010000010",mwrite);-- 0x410 to 0x417 lloadveli <= decodedstrobe(mwadd(11 downto 3), "010000011",mwrite);-- 0x418 to 0x41F lreadpos <= decodedstrobe(ioradd(11 downto 3),"010000100",'1');-- 0x420 to 0x427 end process localdecode; end dataflow;