/ uartr.vhd
uartr.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  
 72  -- Simple UART with 32 bit bus interface
 73  -- 16 byte deep receive FIFO
 74  -- Can read 4,3,2,1 bytes from FIFO depending on data register read offset
 75  -- Base Address = 1 byte
 76  -- Base Address +1 = 2 bytes
 77  -- Base Address +2 = 3 bytes
 78  -- Base Address +3 = 4 bytes
 79  entity uartr is
 80  	port (
 81  		clk : in std_logic;
 82  	 	ibus : in std_logic_vector(31 downto 0);
 83        obus : out std_logic_vector(31 downto 0);
 84  		addr : in std_logic_vector(1 downto 0);
 85        popfifo : in std_logic;
 86  		loadbitrate : in std_logic;
 87  		readbitrate : in std_logic;
 88        clrfifo : in std_logic;
 89  		readfifocount : in std_logic;
 90  		loadmode : in std_logic;
 91  		readmode : in std_logic;
 92  		fifohasdata : out std_logic;
 93  		rxmask : in std_logic;
 94        rxdata : in std_logic
 95  		);
 96  end uartr;
 97  
 98  architecture Behavioral of uartr is
 99  
100  -- FIFO related signals
101  	signal pushdata: std_logic_vector(7 downto 0);
102  	signal popadd0: std_logic_vector(3 downto 0) := x"f";
103  	signal popadd1: std_logic_vector(3 downto 0) := x"f";
104  	signal popadd2: std_logic_vector(3 downto 0) := x"f";
105  	signal popadd3: std_logic_vector(3 downto 0) := x"f";
106  	
107  	signal popdata: std_logic_vector(31 downto 0);
108  	signal datacounter: std_logic_vector(4 downto 0);
109  	signal push: std_logic;  
110  	signal pop: std_logic;  
111  	signal popsize: std_logic_vector(2 downto 0);
112  	signal clear: std_logic;
113  	signal lfifoempty: std_logic; 
114  	signal lfifohasdata: std_logic; 
115  
116  -- uart interface related signals
117  
118  constant DDSWidth : integer := 20;
119  
120  signal BitrateDDSReg : std_logic_vector(DDSWidth-1 downto 0);
121  signal BitrateDDSAccum : std_logic_vector(DDSWidth-1 downto 0);
122  alias  DDSMSB : std_logic is BitrateDDSAccum(DDSWidth-1);
123  signal OldDDSMSB: std_logic;  
124  signal SampleTime: std_logic; 
125  signal BitCount : std_logic_vector(3 downto 0);
126  signal BytePointer : std_logic_vector(2 downto 0) := "000";
127  signal SReg: std_logic_vector(9 downto 0);
128  alias  SregData: std_logic_vector(7 downto 0)is SReg(8 downto 1);
129  alias  StartBit: std_logic is Sreg(0);
130  alias  StopBit: std_logic is Sreg(9);
131  signal RXPipe : std_logic_vector(1 downto 0);
132  signal Go: std_logic; 
133  signal DAV: std_logic;
134  signal ModeReg: std_logic_vector(5 downto 0);
135  alias FalseStart: std_logic is ModeReg(0);-- started recieve but middle of start bit is '1' 
136  alias OverRun: std_logic is ModeReg(1);	-- '0' where stop bit should be
137  alias RXMaskEn: std_logic is ModeReg(3); 	-- enable TXEN of transmit side to disable receive
138  alias FIFOError: std_logic is ModeReg(4); -- pop with no or not enough data
139  alias LostData: std_logic is ModeReg(5); 	-- data overrun
140  
141    component SRL16E
142  --
143      generic (INIT : bit_vector);
144  
145  
146  --
147      port (D   : in  std_logic;
148            CE  : in  std_logic;
149            CLK : in  std_logic;
150            A0  : in  std_logic;
151            A1  : in  std_logic;
152            A2  : in  std_logic;
153            A3  : in  std_logic;
154            Q   : out std_logic); 
155    end component;
156  	
157  			
158  begin
159  
160  	fifosrl0: for i in 0 to 7 generate
161  		asr16e: SRL16E generic map (x"0000") port map(
162   			 D	  => pushdata(i),
163            CE  => push,
164            CLK => clk,
165            A0  => popadd0(0),
166            A1  => popadd0(1),
167            A2  => popadd0(2),
168            A3  => popadd0(3),
169            Q   => popdata(i)
170  			);	
171    	end generate;
172  	
173  	fifosrl1: for i in 0 to 7 generate
174  		asr16e: SRL16E generic map (x"0000") port map(
175   			 D	  => pushdata(i),
176            CE  => push,
177            CLK => clk,
178            A0  => popadd1(0),
179            A1  => popadd1(1),
180            A2  => popadd1(2),
181            A3  => popadd1(3),
182            Q   => popdata(8+i)
183  			);	
184    	end generate;
185  	
186  	fifosrl2: for i in 0 to 7 generate
187  		asr16e: SRL16E generic map (x"0000") port map(
188   			 D	  => pushdata(i),
189            CE  => push,
190            CLK => clk,
191            A0  => popadd2(0),
192            A1  => popadd2(1),
193            A2  => popadd2(2),
194            A3  => popadd2(3),
195            Q   => popdata(16+i)
196  			);	
197    	end generate;
198  	
199  	fifosrl3: for i in 0 to 7 generate
200  		asr16e: SRL16E generic map (x"0000") port map(
201   			 D	  => pushdata(i),
202            CE  => push,
203            CLK => clk,
204            A0  => popadd3(0),
205            A1  => popadd3(1),
206            A2  => popadd3(2),
207            A3  => popadd3(3),
208            Q   => popdata(24+i)
209  			);	
210    	end generate;
211  	
212  	afifo: process (clk,popdata,datacounter)
213  	begin
214  		if rising_edge(clk) then
215  			
216  			if push = '1'  and pop = '0' then
217  				if datacounter /= 16 then	-- a push
218  					-- always increment the data counter if not full
219  					datacounter <= datacounter +1;
220  					popadd0 <= popadd0 +1;						-- popadd must follow data down shiftreg
221  				else
222  					LostData <= '1';
223  				end if;	
224  			end if;		 		
225  						   
226  			if  (pop = '1') and (push = '0') then		-- a pop
227  				if datacounter >= popsize then  
228  					datacounter <= datacounter - popsize;
229  					popadd0 <= popadd0 - popsize;
230  				else
231  					FIFOError <= '1';
232  				end if;	
233  			end if;
234  
235  			if  (pop = '1') and (push = '1') then		-- simultaneaous pop and push
236  				if datacounter >= popsize then			-- note pushdata was not available 
237  				                                       -- when read occured so compare datacounter with popsize
238  					datacounter <= datacounter - (addr);
239  					popadd0 <= popadd0 - (addr);
240  				else												-- if pop is not valid, just do push part
241  					datacounter <= datacounter +1;
242  					popadd0 <= popadd0 +1;
243  					FIFOError <= '1';
244  				end if;	
245  			end if;
246  
247  			if clear = '1' then -- a clear fifo
248  				popadd0  <= (others => '1');
249  				datacounter <= (others => '0');
250  				LostData <= '0';
251  				FIFOError <= '0';
252  			end if;	
253  	
254  
255  		end if; -- clk rise
256  		-- The way this mess works is that we have 4 byte wide FIFOs with duplicated data
257  		-- but the readout point is shifted by one byte for each succeeding FIFO so we can read up to
258  		-- 32 bits (4 bytes) at once. Wasteful, but SRL16s are cheap
259  
260  
261  		popadd1 <= popadd0 -1;		-- note that these are not forced to 0 on underflow
262  		popadd2 <= popadd0 -2;		-- so unused bytes of a less than 4 byte read
263  		popadd3 <= popadd0 -3;		-- will be stale recv data - not good for security reasons!
264  		                           -- if this matters, force to 0 on underflow will result in duplicated
265  											-- current data on unused bytes.
266  			
267  		popsize <= ('0'&addr) +1;
268  		
269  		if datacounter = 0 then
270  			lfifoempty <= '1';
271  		else
272  			lfifoempty <= '0';
273  		end if;
274  		fifohasdata <= not lfifoempty;		 
275  	end process afifo;
276  
277  
278  	asimpleuartrx: process (clk)
279  	begin
280  		if rising_edge(clk) then
281  			RXPipe <= RXPipe(0) & rxdata;  			-- Two stage rx data pipeline to compensate for
282  																-- two clock delay from start bit detection to acquire loop startup
283  																		
284  			if Go = '1' then 
285  				BitRateDDSAccum <= BitRateDDSAccum + BitRateDDSReg;
286  				if SampleTime = '1' then
287  					
288  					if BitCount = 0 then
289  						Go <= '0';
290  						DAV <= '1';
291  						if RXPipe(1) = '0' then
292  							OverRun <= '1';
293  						end if;	
294  					end if;	
295  					
296  					if BitCount = "1001" then	-- false start bit check
297  						if RXPipe(1) = '1' then
298  							Go <= '0';				-- abort receive
299  							FalseStart <= '1';
300  						end if;
301  					end if;	
302  					
303  					SReg <= RXPipe(1) & SReg(9 downto 1);		-- right shift = LSb first
304  					BitCount <= BitCount -1;
305  					
306  				end if;	
307  			else
308  				BitRateDDSAccum <= (others => '0'); 
309  				BitCount <= "1001";
310  			end if;
311  			
312  			if Go = '0' and rxdata = '0' and (rxmask and RXMaskEn) = '0' then		-- start bit detection
313  				Go <= '1';
314  			end if;	
315  			
316  			if DAV = '1' then								-- DAV is just one clock wide
317  				DAV <= '0';
318  			end if;	
319  			
320  			OldDDSMSB <= DDSMSB;							-- for Phase accumulator MSB edge detection
321  
322  			if loadbitrate =  '1' then 
323  				BitRateDDSReg <= ibus(DDSWidth-1 downto 0);				 
324  			end if;
325  			
326  			if loadmode=  '1' then 
327  				ModeReg(3 downto 0) <= ibus(3 downto 0);
328  			end if;
329  
330  		end if; -- clk
331  		
332  		SampleTime <= (not OldDDSMSB) and DDSMSB;		-- sample on rising edge of DDS MSB
333        pushdata <= SRegData;						
334  		push <= DAV;	
335  		pop <= popfifo;
336  		clear <= clrfifo;
337  
338  		obus <= (others => 'Z');
339  		if	readfifocount =  '1' then
340  			obus(4 downto 0) <= datacounter;
341  --			obus(31 downto 5) <= (others => '0');
342  		end if;
343        if readbitrate =  '1' then
344  			obus(DDSWidth-1 downto 0) <= BitRateDDSReg;
345  		end if;
346  		if popfifo =  '1' then
347  			obus <= popdata;
348  		end if;
349  		if readmode =  '1' then
350  			obus(5 downto 0) <= ModeReg;
351  			obus(6) <= rxmask;
352  			obus(7) <= not lfifoempty;
353  			
354  		end if;
355  		fifohasdata <= not lfifoempty;
356  			
357  	end process asimpleuartrx;
358  	
359  end Behavioral;