/ uartx.vhd
uartx.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  -- Copyright (C) 2007, Peter C. Wallace, Mesa Electronics
  8  -- http://www.mesanet.com
  9  --
 10  -- This program is is licensed under a disjunctive dual license giving you
 11  -- the choice of one of the two following sets of free software/open source
 12  -- licensing terms:
 13  --
 14  --    * GNU General Public License (GPL), version 2.0 or later
 15  --    * 3-clause BSD License
 16  -- 
 17  --
 18  -- The GNU GPL License:
 19  -- 
 20  --     This program is free software; you can redistribute it and/or modify
 21  --     it under the terms of the GNU General Public License as published by
 22  --     the Free Software Foundation; either version 2 of the License, or
 23  --     (at your option) any later version.
 24  -- 
 25  --     This program is distributed in the hope that it will be useful,
 26  --     but WITHOUT ANY WARRANTY; without even the implied warranty of
 27  --     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 28  --     GNU General Public License for more details.
 29  -- 
 30  --     You should have received a copy of the GNU General Public License
 31  --     along with this program; if not, write to the Free Software
 32  --     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 33  -- 
 34  -- 
 35  -- The 3-clause BSD License:
 36  -- 
 37  --     Redistribution and use in source and binary forms, with or without
 38  --     modification, are permitted provided that the following conditions
 39  --     are met:
 40  -- 
 41  --         * Redistributions of source code must retain the above copyright
 42  --           notice, this list of conditions and the following disclaimer.
 43  -- 
 44  --         * Redistributions in binary form must reproduce the above
 45  --           copyright notice, this list of conditions and the following
 46  --           disclaimer in the documentation and/or other materials
 47  --           provided with the distribution.
 48  -- 
 49  --         * Neither the name of Mesa Electronics nor the names of its
 50  --           contributors may be used to endorse or promote products
 51  --           derived from this software without specific prior written
 52  --           permission.
 53  -- 
 54  -- 
 55  -- Disclaimer:
 56  -- 
 57  --     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 58  --     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 59  --     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 60  --     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 61  --     COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 62  --     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 63  --     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 64  --     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 65  --     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 66  --     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 67  --     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 68  --     POSSIBILITY OF SUCH DAMAGE.
 69  -- 
 70  
 71  entity uartx is
 72      Port ( clk : in std_logic;
 73  	 		  ibus : in std_logic_vector(31 downto 0);
 74             obus : out std_logic_vector(31 downto 0);
 75  			  addr : in std_logic_vector(1 downto 0);
 76             pushfifo : in std_logic;
 77  			  loadbitrate : in std_logic;
 78             readbitrate : in std_logic;          
 79  			  clrfifo : in std_logic;
 80  			  readfifocount : in std_logic;
 81  			  loadmode : in std_logic;
 82  			  readmode : in std_logic;
 83  			  fifoempty : out std_logic;
 84  			  txen : in std_logic;
 85  			  drven : out std_logic;
 86             txdata : out std_logic
 87            );
 88  end uartx;
 89  
 90  architecture Behavioral of uartx is
 91  
 92  -- FIFO related signals
 93  	signal pushdata: std_logic_vector(33 downto 0);
 94  	signal popadd: std_logic_vector(3 downto 0) := x"f";
 95  	signal popdata: std_logic_vector(33 downto 0);
 96  	alias  byteshere: std_logic_vector(1 downto 0) is popdata(33 downto 32);
 97  	signal datacounter: std_logic_vector(4 downto 0);
 98  	signal push: std_logic;  
 99  	signal pop: std_logic;  
100  	signal clear: std_logic;
101  	signal lfifoempty: std_logic; 
102  	signal fifohasdata: std_logic; 
103  
104  -- uart interface related signals
105  
106  constant DDSWidth : integer := 20;
107  
108  signal BitrateDDSReg : std_logic_vector(DDSWidth-1 downto 0);
109  signal BitrateDDSAccum : std_logic_vector(DDSWidth-1 downto 0);
110  alias  DDSMSB : std_logic is BitrateDDSAccum(DDSWidth-1);
111  signal OldDDSMSB: std_logic;  
112  signal SampleTime: std_logic; 
113  signal BitCount : std_logic_vector(3 downto 0);
114  signal BytePointer : std_logic_vector(2 downto 0) := "000";
115  signal SReg: std_logic_vector(10 downto 0);
116  signal SendData: std_logic_vector(7 downto 0);
117  alias  SregData: std_logic_vector(7 downto 0)is SReg(9 downto 2);
118  alias StartBit: std_logic is Sreg(1);
119  alias StopBit: std_logic is Sreg(10);
120  alias IdleBit: std_logic is Sreg(0);
121  signal Go: std_logic := '0'; 
122  signal ModeReg: std_logic_vector(6 downto 0);
123  alias DriveEnDelay: std_logic_vector(3 downto 0) is ModeReg (3 downto 0);
124  alias FIFOError: std_logic is ModeReg(4);
125  alias DriveEnAuto: std_logic is ModeReg(5);
126  alias DriveEnBit: std_logic is ModeReg(6);
127  signal DriveEnable: std_logic;
128  signal DriveEnHold: std_logic;
129  signal WaitingForDrive: std_logic;
130  signal DriveDelayCount: std_logic_vector(3 downto 0);
131  
132  
133    component SRL16E
134  --
135      generic (INIT : bit_vector);
136  
137  
138  --
139      port (D   : in  std_logic;
140            CE  : in  std_logic;
141            CLK : in  std_logic;
142            A0  : in  std_logic;
143            A1  : in  std_logic;
144            A2  : in  std_logic;
145            A3  : in  std_logic;
146            Q   : out std_logic); 
147    end component;
148  	
149  			
150  begin
151  
152  	fifosrl: for i in 0 to 33 generate
153  		asr16e: SRL16E generic map (x"0000") port map(
154   			 D	  => pushdata(i),
155            CE  => push,
156            CLK => clk,
157            A0  => popadd(0),
158            A1  => popadd(1),
159            A2  => popadd(2),
160            A3  => popadd(3),
161            Q   => popdata(i)
162  			);	
163    	end generate;
164  
165  	
166  
167  	afifo: process (clk,popdata,datacounter)
168  	begin
169  		if rising_edge(clk) then
170  			
171  			if push = '1'  and pop = '0'  then
172  				if datacounter /= 16 then	-- a push
173  					-- always increment the data counter if not full
174  					datacounter <= datacounter +1;
175  					popadd <= popadd +1;						-- popadd must follow data down shiftreg
176  				else
177  					FIFOError <= '1';
178  				end if;	
179  			end if;		 		
180  						   
181  			if  (pop = '1') and (push = '0') and (lfifoempty = '0') then	-- a pop
182  				-- always decrement the data counter if not empty
183  				datacounter <= datacounter -1;
184  				popadd <= popadd -1;
185  			end if;
186  
187  -- if both push and pop are asserted we dont change either counter
188  	  
189  			if clear = '1' then -- a clear fifo
190  				popadd  <= (others => '1');
191  				datacounter <= (others => '0');
192  				FIFOError <= '0';
193  			end if;	
194  	
195  
196  		end if; -- clk rise
197  		if datacounter = 0 then
198  			lfifoempty <= '1';
199  		else
200  			lfifoempty <= '0';
201  		end if;
202  		fifohasdata <= not lfifoempty;		 
203  	end process afifo;
204  
205  
206  	asimpleuarttx: process (clk)
207  	begin
208  		if rising_edge(clk) then
209  			if Go = '1' then 
210  				BitRateDDSAccum <= BitRateDDSAccum - BitRateDDSReg;
211  				if SampleTime = '1' then
212  					SReg <= '1' & SReg(10 downto 1);		-- right shift = LSb first
213  					BitCount <= BitCount -1;
214  					if BitCount = 0 then
215  						Go <= '0';
216  					end if;	
217  				end if;	
218  			else
219  				BitRateDDSAccum <= (others => '0');
220  			end if;
221  			
222  
223  			if pop = '1' then 					-- just one clock
224  				pop <= '0';
225  			end if;
226  			
227  			if Go = '0' then
228  				StartBit <= '0';
229  				StopBit <= '1';
230  				IdleBit <= '1';				
231  				BitCount <= "1010";
232  				if fifohasdata = '1' and pop = '0' and txen = '1' and DriveEnHold = '0' then   		                                                                                                                                 -- UART SReg not busy and we have data
233  					if bytepointer <= ('0'& byteshere) then 	-- still bytes to send in this double word
234  						SRegData <= SendData;
235  						Go <= '1';						
236  						bytepointer <= bytepointer +1;
237  					else
238  						pop <= '1';
239  						bytepointer <= "000";
240  					end if;
241  				end if;				
242  			end if;		
243  			
244  		
245  			if DriveEnable = '0' then
246  				DriveDelayCount <= DriveEnDelay;
247  			else
248  				if WaitingForDrive = '1' then
249  					DriveDelayCount <= DriveDelayCount -1;
250  				end if;	
251  			end if;
252  			
253  			
254  			OldDDSMSB <= DDSMSB;
255  
256  			if loadbitrate =  '1' then 
257  				BitRateDDSReg <= ibus(DDSWidth-1 downto 0);				 
258  			end if;
259  
260  			if loadmode =  '1' then 
261  				ModeReg(3 downto 0) <= ibus(3 downto 0);
262  				ModeReg(6 downto 5) <= ibus(6 downto 5);
263  			end if;
264  
265  		end if; -- clk
266  		
267  		SampleTime <= (not OldDDSMSB) and DDSMSB;
268        pushdata <= addr & ibus;		-- msbs of FIFO data are address bits to specify data size	
269  		push <= pushfifo;	
270  		clear <= clrfifo;
271  		
272  		if DriveDelayCount /= 0 then 
273  			WaitingForDrive <= '1';
274  		else
275  			WaitingForDrive <= '0';
276  		end if;	
277  		
278  		DriveEnHold <= (not DriveEnable) or WaitingForDrive;
279  		
280  		if DriveEnAuto = '1' then 
281  			DriveEnable <= (Go or Pop or FIFOHasData) and txen; 		-- note that this means txen should never be removed 																						-- when there is data to xmit
282  		else																			-- in the middle of a block transmission
283  			DriveEnable <= DriveEnBit;
284  		end if;	
285  		
286  		case bytepointer(1 downto 0) is 
287  			when "00" => SendData <= PopData(7 downto 0);
288  			when "01" => SendData <= PopData(15 downto 8);
289  			when "10" => SendData <= PopData(23 downto 16);
290  			when "11" => SendData <= PopData(31 downto 24);
291  			when others => null;
292  		end case;
293  		
294  		obus <= (others => 'Z');
295  		if	readfifocount =  '1' then
296  			obus(4 downto 0) <= datacounter;
297  			obus(31 downto 5) <= (others => '0');
298  		end if;
299        if readbitrate =  '1' then
300  			obus(DDSWidth-1 downto 0) <= BitRateDDSReg;
301  		end if;
302  
303  		if readmode =  '1' then
304  			obus(6 downto 0) <= ModeReg;
305  			obus(7) <= Go or Pop or FIFOHasData;
306  		end if;
307  
308  		txdata<= SReg(0);
309  		fifoempty <= lfifoempty;
310  		drven <= DriveEnable;
311  		
312  	end process asimpleuarttx;
313  	
314  end Behavioral;