/ kubstepgenzi.vhd
kubstepgenzi.vhd
  1  library IEEE;
  2  use IEEE.STD_LOGIC_1164.ALL;
  3  use IEEE.STD_LOGIC_ARITH.ALL;
  4  use IEEE.STD_LOGIC_UNSIGNED.ALL;
  5  
  6  
  7  --
  8  -- Copyright (C) 2007, Peter C. Wallace, Mesa Electronics
  9  -- http://www.mesanet.com
 10  --
 11  -- This program is is licensed under a disjunctive dual license giving you
 12  -- the choice of one of the two following sets of free software/open source
 13  -- licensing terms:
 14  --
 15  --    * GNU General Public License (GPL), version 2.0 or later
 16  --    * 3-clause BSD License
 17  -- 
 18  --
 19  -- The GNU GPL License:
 20  -- 
 21  --     This program is free software; you can redistribute it and/or modify
 22  --     it under the terms of the GNU General Public License as published by
 23  --     the Free Software Foundation; either version 2 of the License, or
 24  --     (at your option) any later version.
 25  -- 
 26  --     This program is distributed in the hope that it will be useful,
 27  --     but WITHOUT ANY WARRANTY; without even the implied warranty of
 28  --     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 29  --     GNU General Public License for more details.
 30  -- 
 31  --     You should have received a copy of the GNU General Public License
 32  --     along with this program; if not, write to the Free Software
 33  --     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 34  -- 
 35  -- 
 36  -- The 3-clause BSD License:
 37  -- 
 38  --     Redistribution and use in source and binary forms, with or without
 39  --     modification, are permitted provided that the following conditions
 40  --     are met:
 41  -- 
 42  --         * Redistributions of source code must retain the above copyright
 43  --           notice, this list of conditions and the following disclaimer.
 44  -- 
 45  --         * Redistributions in binary form must reproduce the above
 46  --           copyright notice, this list of conditions and the following
 47  --           disclaimer in the documentation and/or other materials
 48  --           provided with the distribution.
 49  -- 
 50  --         * Neither the name of Mesa Electronics nor the names of its
 51  --           contributors may be used to endorse or promote products
 52  --           derived from this software without specific prior written
 53  --           permission.
 54  -- 
 55  -- 
 56  -- Disclaimer:
 57  -- 
 58  --     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 59  --     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 60  --     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 61  --     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 62  --     COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 63  --     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 64  --     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 65  --     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 66  --     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 67  --     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 68  --     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 69  --     POSSIBILITY OF SUCH DAMAGE.
 70  -- 
 71  
 72  
 73  entity stepgeni is
 74          generic (
 75  			buswidth : integer;
 76  			timersize : integer;
 77  			tablewidth : integer;
 78  			asize : integer;
 79  			rsize : integer;
 80  			lsize : integer
 81  			);
 82  			Port ( clk : in std_logic;
 83  	 		  ibus : in std_logic_vector(buswidth-1 downto 0);
 84             obus : out std_logic_vector(buswidth-1 downto 0);
 85             loadsteprate : in std_logic;
 86  			  loadaccum : in std_logic;
 87             loadstepmode : in std_logic;
 88  			  loaddirsetuptime : in std_logic;
 89  			  loaddirholdtime : in std_logic;
 90  			  loadpulseactivetime : in std_logic;
 91  			  loadpulseidletime : in std_logic;
 92  			  loadtable : in std_logic;	
 93  			  loadtablemax : in std_logic;	
 94             readsteprate : in std_logic;
 95  			  readaccum : in std_logic;
 96             readstepmode : in std_logic;
 97  			  readdirsetuptime : in std_logic;
 98  			  readdirholdtime : in std_logic;
 99  			  readpulseactivetime : in std_logic;
100  			  readpulseidletime : in std_logic;			  
101  			  readtable : in std_logic;	
102  			  readtablemax : in std_logic;	
103             basicrate : in std_logic;
104             hold : in std_logic;
105  			  index : in std_logic;
106  			  probe : in std_logic;
107             stout : out std_logic_vector(tablewidth-1 downto 0)
108            );
109  end stepgeni;
110  
111  architecture Behavioral of stepgeni is
112  
113  
114  -- Step Generator	related signals
115  
116  	signal stepaccum: std_logic_vector(asize-1 downto 0);
117  	signal nextaccum: std_logic_vector(asize-1 downto 0);
118  	alias stepmsbs: std_logic_vector(1 downto 0) is stepaccum(rsize-1 downto rsize -2);
119  	alias stepmsb: std_logic is stepaccum(rsize -1);
120  	alias nextmsb: std_logic is nextaccum(rsize -1);
121  	signal dstepmsb : std_logic;
122  	signal ddshold : std_logic;	 
123  	signal steprate: std_logic_vector(rsize -1 downto 0);
124  	alias  stepdir: std_logic is steprate(rsize -1);
125  	signal dstepdir  : std_logic;
126  	signal stepdirout  : std_logic;
127  	signal pulsewait : std_logic;
128  	signal steppulse : std_logic := '0';
129  	signal dpulsewait : std_logic := '0';
130  	signal dirsetupwait  : std_logic;
131  	signal dirholdwait  : std_logic;
132  	signal dirshwait  : std_logic;
133  	signal dirhold  : std_logic;
134  	signal dirshcount: std_logic_vector(timersize-1 downto 0);
135  	signal pulsewidthcount: std_logic_vector(timersize-1 downto 0);
136  	signal dirsetuptime: std_logic_vector(timersize -1 downto 0);
137  	signal dirholdtime: std_logic_vector(timersize -1 downto 0);
138  	signal pulseactivetime: std_logic_vector(timersize -1 downto 0);
139  	signal pulseidletime: std_logic_vector(timersize -1 downto 0);
140  	signal stepmode: std_logic_vector(6 downto 0);
141  	signal localout: std_logic_vector(tablewidth-1 downto 0);
142  	signal wewouldcount : std_logic;
143   	signal dirchange : std_logic;
144   	signal waitforhold : std_logic;
145   	signal waitforpulse : std_logic;
146  	signal tableptr: std_logic_vector(3 downto 0);
147  	signal tablemax: std_logic_vector(3 downto 0);
148  	signal tabledata: std_logic_vector(tablewidth-1 downto 0);
149  	-- index and probe stuff;
150  	alias latchonindex : std_logic is stepmode(2);
151  	alias indexpol : std_logic is stepmode(3);
152  	alias latchonprobe : std_logic is stepmode(4);
153  	alias probepol : std_logic is stepmode(5);
154     alias justonce : std_logic is stepmode(6);
155  	signal indexflt: std_logic_vector(3 downto 0);
156  	signal probeflt: std_logic_vector(3 downto 0);
157  	signal indexd: std_logic_vector(1 downto 0);
158  	signal probed: std_logic_vector(1 downto 0);
159  	signal countlatch : std_logic_vector(lsize-1 downto 0);
160  	component SRL16E
161  --
162      generic (INIT : bit_vector);
163  
164  
165  --
166      port (D   : in  std_logic;
167            CE  : in  std_logic;
168            CLK : in  std_logic;
169            A0  : in  std_logic;
170            A1  : in  std_logic;
171            A2  : in  std_logic;
172            A3  : in  std_logic;
173            Q   : out std_logic); 
174  	end component;
175  	
176  			
177  begin
178  
179  	steptable: for i in 0 to tablewidth -1 generate
180  		asr16e: SRL16E generic map (x"0000") port map(
181   			 D	  => ibus(i),
182            CE  => loadtable,
183            CLK => clk,
184            A0  => tableptr(0),
185            A1  => tableptr(1),
186            A2  => tableptr(2),
187            A3  => tableptr(3),
188            Q   => tabledata(i)
189  			);	
190    	end generate;
191  
192  	astepgen: process (clk,stepdirout, steprate, nextaccum, stepaccum,dirshwait,
193  	                   dirholdwait, pulsewait, dpulsewait,dirchange,wewouldcount,waitforpulse,
194  							 dirsetupwait, pulsewidthcount, dirshcount, dirhold, waitforhold,
195  							 readaccum, tabledata, stepmode, steppulse, stepmsbs,localout)
196  	begin
197  		if rising_edge(clk) then
198  
199  			if basicrate = '1' and hold = '0' and ddshold = '0' then	 			-- our basic step rate DDS
200  				stepaccum <= nextaccum;
201  				dstepdir <= stepdir;															-- only updated when we add
202  			end if;
203  
204  			if pulsewait = '1' then 							  							-- our two timers
205  				pulsewidthcount <= pulsewidthcount -1;									-- we share dirshcount between setup and hold functions 
206  			end if;				
207  			
208  			if (pulsewait = '0') and (dpulsewait = '1') and (steppulse = '1') then			
209  				pulsewidthcount <= pulseidletime;										-- output pulse idle time
210  				steppulse <= '0';																-- clear our output pulse
211  			end if;
212  			
213  			if dirshwait = '1' then 
214  				dirshcount <= dirshcount -1;
215  			end if;				
216  
217  			if (stepmsb = '0' and dstepmsb = '1' and dstepdir = '0') 				-- overflow = we counted up
218  			or (stepmsb = '1' and dstepmsb = '0' and dstepdir = '1') then 		-- underflow = we counted down		  		-- the output of the DDS
219  				pulsewidthcount <= pulseactivetime;										-- output pulse active time								
220  				steppulse <= '1';
221  				dirshcount <= dirholdtime;													-- set pulse to dir change hold timer
222  				dirhold <= '1';	 															--	set our flag to indicate			
223  			else
224  				if dirholdwait = '0' then  												-- no change during hold time 
225  					if dirchange = '1' then					  								-- we need to change the external direction signal
226  						dirshcount <= dirsetuptime;										-- set dir change to next pulse setup time
227  						dirhold <= '0';														-- set our flag to indicate
228  						stepdirout <= stepdir;												-- update the output direction
229  					end if;																		-- our timer is for setup time
230  				end if;			
231  			end if;																				-- our timer is for hold time			
232  
233  			
234  			if (stepmsb = '0' and dstepmsb = '1' and dstepdir = '0') then 		-- we counted up		
235  				if (tableptr = tablemax) then
236  					tableptr <= x"0";
237  				else
238  					tableptr <= tableptr +1;
239  				end if;
240  			end if;
241  			if (stepmsb = '1' and dstepmsb = '0' and dstepdir = '1') then		-- we counted down
242  				if (tableptr = x"0") then
243  					tableptr <= tablemax;
244  				else
245  					tableptr <= tableptr -1;
246  				end if;
247  			end if;	
248  			
249  			if loadstepmode = '1' then					   								-- our register writes
250  				stepmode <= ibus(6 downto 0);
251  			end if;
252  			if loadsteprate = '1' then
253  				steprate <= ibus(rsize -1 downto 0);
254  			end if;
255  			if loadaccum = '1' then
256  				stepaccum(asize -1 downto asize-buswidth) <= ibus;
257  				dstepmsb <= ibus(buswidth-1);												-- avoid generating a step when loading accumulator
258  			end if;
259  			if loaddirsetuptime = '1' then					   
260  				dirsetuptime <= ibus(timersize -1 downto 0);
261  			end if;
262  			if loaddirholdtime = '1' then					   
263  				dirholdtime <= ibus(timersize -1 downto 0);
264  			end if;
265  			if loadpulseactivetime = '1' then					   
266  				pulseactivetime <= ibus(timersize -1 downto 0);
267  			end if;
268  			if loadpulseidletime = '1' then					   
269  				pulseidletime <= ibus(timersize -1 downto 0);
270  			end if;			
271  
272  			if loadtablemax = '1' then					   
273  				tablemax <= ibus(3 downto 0);
274  				tableptr <= x"0";
275  			end if;
276  			
277  			dpulsewait <= pulsewait;
278  			dstepmsb <= stepmsb;
279  
280  			-- index/probe logic
281  			
282  			if index = '1' then
283  				if indexflt /= x"F" then
284  					indexflt <= indexflt + 1;
285  				end if;
286  			else	
287  				if indexflt /= x"0" then
288  					indexflt <= indexflt - 1;
289  				end if;
290  			end if;
291  			if indexflt = x"0" then
292  				indexd(0) <= '0';
293  			end if;
294  			if indexflt = x"F" then
295  				indexd(0) <= '1';
296  			end if;
297  			indexd(1) <= indexd(0);
298  
299  			if probe = '1' then
300  				if probeflt /= x"F" then
301  					probeflt <= probeflt + 1;
302  				end if;
303  			else	
304  				if probeflt /= x"0" then
305  					probeflt <= probeflt - 1;
306  				end if;
307  			end if;
308  			if probeflt = x"0" then
309  				probed(0) <= '0';
310  			end if;
311  			if probeflt = x"F" then
312  				probed(0) <= '1';
313  			end if;
314  			probed(1) <= probed(0);				
315  			
316  			if (indexd = "01" and latchonindex = '1' and indexpol = '1') or
317  				(indexd = "10" and latchonindex = '1' and indexpol = '0') then
318  				countlatch <= stepaccum(asize-1 downto asize-lsize);
319  				if justonce = '1' then
320  					latchonindex <= '0';
321  				end if;
322  			end if;		
323  
324  			if (probed = "01" and latchonprobe = '1' and probepol = '1') or
325  				(probed = "10" and latchonprobe = '1' and probepol = '0') then
326  				countlatch <= stepaccum(asize-1 downto asize-lsize);
327  				if justonce = '1' then
328  					latchonprobe <= '0';
329  				end if;
330  			end if;		
331  		
332  			
333  		end if; -- clk									
334  
335  		dirchange <= stepdirout xor stepdir;			
336  
337  		if (stepmsb = '1' and nextmsb = '0' and stepdir = '0')			-- overflow = we would count up
338  		or (stepmsb = '0' and nextmsb = '1' and stepdir = '1')  then 	-- underflow = we would count down		
339  			wewouldcount <= '1';
340  		else
341  			wewouldcount <= '0';
342  		end if;	
343  
344  		waitforhold <= dirholdwait and dirchange;
345  		waitforpulse <= pulsewait or dpulsewait;
346  
347  		nextaccum <= signed(stepaccum)+ signed(steprate);				-- to lookahead
348  
349  		if (wewouldcount = '1') and 
350  --		(((waitforhold  = '1') or (dirsetupwait = '1') or (waitforpulse = '1'))) -- misses the case where Dirhold has timed out!
351  		(((waitforhold  = '1') or (dirsetupwait = '1') or (waitforpulse = '1') or (dirchange = '1')))
352  		then					-- need to pause
353  			ddshold <= '1';
354  		else
355  			ddshold <= '0';												
356  		end if;			
357  		
358  		if pulsewidthcount = 0  then
359  			pulsewait <= '0';
360  		else
361  			pulsewait <= '1';
362  		end if;
363  
364  		if dirshcount = 0 then
365  			dirshwait <= '0';
366  		else
367  			dirshwait <= '1';
368  		end if;
369  
370  		dirholdwait <= (dirhold and dirshwait);
371  		dirsetupwait <= (not dirhold) and dirshwait;
372  		
373        obus <= (others => 'Z');     
374  
375  --		if readsteprate =  '1' then
376  --			obus(rsize -1 downto 0) <= steprate;
377  --		end if;
378  
379  		if readaccum =  '1' then
380  			obus <= stepaccum(asize -1 downto asize-buswidth);
381  		end if;
382  
383  		if readstepmode =  '1' then							
384  			obus(6 downto 0) <= stepmode;
385  			obus(buswidth-1 downto buswidth-lsize) <= countlatch;
386  		end if;
387  
388  --		if readdirsetuptime =  '1' then
389  --			obus(timersize -1 downto 0) <= dirsetuptime;			-- most register readbacks commented out for size
390  --			obus(31 downto timersize) <= (others => '0');
391  --		end if;
392  --		if readdirholdtime =  '1' then
393  --			obus(timersize -1 downto 0) <= dirholdtime;
394  --			obus(31 downto timersize) <= (others => '0');
395  --		end if;
396  --		if readpulseactivetime =  '1' then
397  --			obus(timersize -1 downto 0) <= pulsewidth;
398  --			obus(31 downto timersize) <= (others => '0');
399  --		end if;
400  --		if readpulseidletime =  '1' then
401  --			obus(timersize -1 downto 0) <= pulseidle;
402  --			obus(31 downto timersize) <= (others => '0');
403  --		end if;
404  
405  
406  		localout <= tabledata;  -- this is the default unless: 
407  		case stepmode(1 downto 0) is
408  			when "00"  =>
409  				localout(0) <= steppulse; 								-- step
410  				localOut(1) <= stepdirout;	 							-- dir
411  			when "01" =>
412  				localout(0) <= steppulse and (not stepdirout); 	-- count up
413  				localOut(1) <= steppulse and stepdirout;	   	-- count down
414  			when  "10" =>
415  				case stepmsbs is
416  					when "00" => localout(1 downto 0) <= "00";					-- quadrature
417  					when "01" => localout(1 downto 0) <= "01";			
418  					when "10" => localout (1 downto 0)<= "11";
419  					when "11" => localout(1 downto 0) <= "10";
420  					when others => null; 
421  				end case;
422  			when others => null;
423  		end case;
424  		stout <= localout;
425  
426  	end process astepgen;
427  	
428  end Behavioral;