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