/ 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;