/ uartx8.vhd
uartx8.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 uartx8 is
 72      Port ( clk : in std_logic;
 73  	 		  ibus : in std_logic_vector(7 downto 0);
 74             obus : out std_logic_vector(7 downto 0);
 75             pushfifo : in std_logic;
 76  			  loadbitratel : in std_logic;
 77  			  loadbitratem : in std_logic;
 78  			  loadbitrateh : in std_logic;
 79             readbitratel : in std_logic;          
 80             readbitratem : in std_logic;          
 81             readbitrateh : in std_logic;          
 82  			  clrfifo : in std_logic;
 83  			  readfifocount : in std_logic;
 84  			  loadmode : in std_logic;
 85  			  readmode : in std_logic;
 86  			  fifoempty : out std_logic;
 87  			  txen : in std_logic;
 88  			  drven : out std_logic;
 89             txdata : out std_logic
 90            );
 91  end uartx8;
 92  
 93  architecture Behavioral of uartx8 is
 94  
 95  -- FIFO related signals
 96  	signal pushdata: std_logic_vector(7 downto 0);
 97  	signal popadd: std_logic_vector(3 downto 0) := x"F";
 98  	signal popdata: std_logic_vector(7 downto 0);
 99  	signal datacounter: std_logic_vector(4 downto 0);
100  	signal push: std_logic;  
101  	signal pop: std_logic;  
102  	signal clear: std_logic;
103  	signal lfifoempty: std_logic; 
104  	signal fifohasdata: std_logic; 
105  
106  -- uart interface related signals
107  
108  constant DDSWidth : integer := 20;
109  
110  signal BitrateDDSReg : std_logic_vector(DDSWidth-1 downto 0);
111  signal BitrateDDSAccum : std_logic_vector(DDSWidth-1 downto 0);
112  alias  DDSMSB : std_logic is BitrateDDSAccum(DDSWidth-1);
113  signal OldDDSMSB: std_logic;  
114  signal SampleTime: std_logic; 
115  signal BitCount : std_logic_vector(3 downto 0);
116  signal SReg: std_logic_vector(10 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(5 downto 0);
123  alias DriveEnDelay: std_logic_vector(3 downto 0) is ModeReg (3 downto 0);
124  alias DriveEnAuto: std_logic is ModeReg(4);
125  alias DriveEnBit: std_logic is ModeReg(5);
126  signal DriveEnable: std_logic;
127  signal DriveEnHold: std_logic;
128  signal WaitingForDrive: std_logic;
129  signal DriveDelayCount: std_logic_vector(3 downto 0);
130  
131  
132    component SRL16E
133  --
134      generic (INIT : bit_vector);
135  
136  
137  --
138      port (D   : in  std_logic;
139            CE  : in  std_logic;
140            CLK : in  std_logic;
141            A0  : in  std_logic;
142            A1  : in  std_logic;
143            A2  : in  std_logic;
144            A3  : in  std_logic;
145            Q   : out std_logic); 
146    end component;
147  	
148  			
149  begin
150  
151  	fifosrl: for i in 0 to 7 generate
152  		asr16e: SRL16E generic map (x"0000") port map(
153   			 D	  => pushdata(i),
154            CE  => push,
155            CLK => clk,
156            A0  => popadd(0),
157            A1  => popadd(1),
158            A2  => popadd(2),
159            A3  => popadd(3),
160            Q   => popdata(i)
161  			);	
162    	end generate;
163  
164  	
165  
166  	afifo: process (clk,popdata,datacounter,lfifoempty)
167  	begin
168  		if rising_edge(clk) then
169  			
170  			if push = '1'  and pop = '0' and datacounter /= 16 then	-- a push
171  		 		-- always increment the data counter if not full
172  				datacounter <= datacounter +1;
173  				popadd <= popadd +1;						-- popadd must follow data down shiftreg
174  			end if;		 		
175  						   
176  			if  (pop = '1') and (push = '0') and (lfifoempty = '0') then	-- a pop
177  				-- always decrement the data counter if not empty
178  				datacounter <= datacounter -1;
179  				popadd <= popadd -1;
180  			end if;
181  
182  -- if both push and pop are asserted we dont change either counter
183  	  
184  			if clear = '1' then -- a clear fifo
185  				popadd  <= (others => '1');
186  				datacounter <= (others => '0');
187  			end if;	
188  	
189  
190  		end if; -- clk rise
191  		if datacounter = 0 then
192  			lfifoempty <= '1';
193  		else
194  			lfifoempty <= '0';
195  		end if;
196  		fifohasdata <= not lfifoempty;		 
197  	end process afifo;
198  
199  	asimpleuarttx: process (clk,OldDDSMSB, BitrateDDSAccum, ibus, pushfifo,
200  									clrfifo, DriveDelayCount, DriveEnable, DriveEnAuto,
201  									Go, pop, fifohasdata, txen, ModeReg, readfifocount,
202  									datacounter, readbitratel, BitrateDDSReg, readbitratem, 
203  									readbitrateh, readmode, SReg, lfifoempty, waitingfordrive )
204  	begin
205  		if rising_edge(clk) then
206  			if Go = '1' then 
207  				BitRateDDSAccum <= BitRateDDSAccum - BitRateDDSReg;
208  				if SampleTime = '1' then
209  					SReg <= '1' & SReg(10 downto 1);		-- right shift = LSb first
210  					BitCount <= BitCount -1;
211  					if BitCount = 0 then
212  						Go <= '0';
213  					end if;	
214  				end if;	
215  			else
216  				BitRateDDSAccum <= (others => '0');
217  			end if;
218  			
219  
220  			if pop = '1' then 					-- just one clock
221  				pop <= '0';
222  			end if;
223  			
224  			if Go = '0' then
225  				StartBit <= '0';
226  				StopBit <= '1';
227  				IdleBit <= '1';				
228  				BitCount <= "1010";
229  				if fifohasdata = '1' and pop = '0' and txen = '1' and DriveEnHold = '0' then  -- UART SReg not busy and we have data			
230  					pop <= '1';							
231  					SRegData <= popdata;
232  					Go <= '1';						
233  				end if;				
234  			end if;		
235  			
236  		
237  			if DriveEnable = '0' then
238  				DriveDelayCount <= DriveEnDelay;
239  			else
240  				if WaitingForDrive = '1' then
241  					DriveDelayCount <= DriveDelayCount -1;
242  				end if;	
243  			end if;
244  			
245  			
246  			OldDDSMSB <= DDSMSB;
247  
248  			if loadbitratel =  '1' then 
249  				BitRateDDSReg(7 downto 0) <= ibus;				 
250  			end if;
251  			if loadbitratem =  '1' then 
252  				BitRateDDSReg(15 downto 8) <= ibus;				 
253  			end if;
254  			if loadbitrateh =  '1' then 
255  				BitRateDDSReg(19 downto 16) <= ibus(3 downto 0);				 
256  			end if;
257  
258  			if loadmode =  '1' then 
259  				ModeReg<= ibus(5 downto 0);				 
260  			end if;
261  
262  		end if; -- clk
263  		
264  		SampleTime <= (not OldDDSMSB) and DDSMSB;
265        pushdata <= ibus;				
266  		push <= pushfifo;	
267  		clear <= clrfifo;
268  		
269  		if DriveDelayCount /= 0 then 
270  			WaitingForDrive <= '1';
271  		else
272  			WaitingForDrive <= '0';
273  		end if;	
274  		
275  		DriveEnHold <= (not DriveEnable) or WaitingForDrive;
276  		
277  		if DriveEnAuto = '1' then 
278  			DriveEnable <= (Go or Pop or FIFOHasData) and txen; 		-- note that this means txen should never be removed 																						-- when there is data to xmit
279  		else																			-- in the middle of a block transmission
280  			DriveEnable <= DriveEnBit;
281  		end if;	
282  		
283  		
284  		obus <= (others => 'Z');
285  		if	readfifocount =  '1' then
286  			obus(4 downto 0) <= datacounter;
287  			obus(7 downto 5) <= (others => '0');
288  		end if;
289  
290        if readbitratel =  '1' then
291  			obus <= BitRateDDSReg(7 downto 0);
292  		end if;
293        if readbitratem =  '1' then
294  			obus <= BitRateDDSReg(15 downto 8);
295  		end if;
296        if readbitrateH =  '1' then
297  			obus(3 downto 0) <= BitRateDDSReg(19 downto 16);
298  		end if;
299  
300  		if readmode =  '1' then
301  			obus(5 downto 0) <= ModeReg;
302  			obus(6) <= txen;
303  			obus(7) <= Go or Pop or FIFOHasData;
304  		end if;
305  
306  		txdata <= SReg(0);
307  		fifoempty <= lfifoempty;
308  		drven <= DriveEnable;
309  		
310  	end process asimpleuarttx;
311  end Behavioral;