/ pktuartr.vhd
pktuartr.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 73 use work.log2.all; 74 75 entity pktuartr is 76 generic (MaxFrameSize: integer); -- in bytes (-1) maximum is 2K bytes 77 Port (clk : in std_logic; 78 ibus : in std_logic_vector(31 downto 0); 79 obus : out std_logic_vector(31 downto 0); 80 popdata : in std_logic; 81 poprc: in std_logic; 82 loadbitrate : in std_logic; 83 readbitrate : in std_logic; 84 loadmode : in std_logic; 85 readmode : in std_logic; 86 rxmask : in std_logic; 87 rxdata : in std_logic 88 ); 89 end pktuartr; 90 91 architecture Behavioral of pktuartr is 92 93 -- buffer related signals 94 signal InAdd: std_logic_vector(log2(MaxFrameSize) -3 downto 0); 95 signal OutAdd: std_logic_vector(log2(MaxFrameSize) -3 downto 0); 96 signal OutData: std_logic_vector(31 downto 0); 97 signal PushData: std_logic; 98 signal FrameBufferEmpty: std_logic; 99 100 -- frame FIFO related signals 101 signal PushRC: std_logic; 102 signal RFrameCount: std_logic_vector(4 downto 0) := "00000"; 103 signal RCPopAdd: std_logic_vector(3 downto 0) := "1111"; 104 signal RCFIFOEmpty : std_logic; 105 signal RCFIFOError: std_logic; 106 signal RCPopData: std_logic_vector(log2(maxFrameSize)-1 downto 0); 107 signal ErrPopData: std_logic_vector(1 downto 0); 108 -- uart interface related signals 109 110 constant DDSWidth : integer := 20; 111 112 signal BitrateDDSReg : std_logic_vector(DDSWidth-1 downto 0); 113 signal BitrateDDSAccum : std_logic_vector(DDSWidth-1 downto 0); 114 alias DDSMSB : std_logic is BitrateDDSAccum(DDSWidth-1); 115 signal OldDDSMSB: std_logic; 116 signal SampleTime: std_logic; 117 signal DelayTime: std_logic; 118 signal BitCount : std_logic_vector(3 downto 0); 119 signal BytePointer : std_logic_vector(1 downto 0) := "00"; 120 signal RDataLatch : std_logic_vector(31 downto 0); 121 signal SReg: std_logic_vector(9 downto 0); 122 alias SRegData: std_logic_vector(7 downto 0)is SReg(9 downto 2); 123 alias StartBit: std_logic is Sreg(0); 124 alias StopBit: std_logic is Sreg(9); 125 signal RXPipe : std_logic_vector(1 downto 0); 126 signal RecvCount: std_logic_vector(log2(MaxFrameSize)-1 downto 0); 127 signal Go: std_logic; 128 signal FDGo: std_logic; 129 signal Clear: std_logic; 130 signal ModeReg: std_logic_vector(15 downto 0); 131 alias FrameDelay: std_logic_vector(7 downto 0) is ModeReg(15 downto 8); 132 signal FrameDelayCount: std_logic_vector(7 downto 0); 133 signal FrameTimeout: std_logic; 134 alias FalseStart: std_logic is ModeReg(0);-- started recieve but middle of start bit is '1' 135 alias OverRun: std_logic is ModeReg(1); -- '0' where stop bit should be 136 alias RXMaskEn: std_logic is ModeReg(2); -- enable TXEN of transmit side to disable receive 137 alias RXEnable: std_logic is ModeReg(3); -- RX enable 138 signal RXErrs: std_logic_vector(1 downto 0); 139 signal ClrRXErrs: std_logic; 140 signal ClrRXErrsD: std_logic; 141 142 component SRL16E 143 -- 144 generic (INIT : bit_vector); 145 146 147 -- 148 port (D : in std_logic; 149 CE : in std_logic; 150 CLK : in std_logic; 151 A0 : in std_logic; 152 A1 : in std_logic; 153 A2 : in std_logic; 154 A3 : in std_logic; 155 Q : out std_logic); 156 end component; 157 158 159 begin 160 161 buffram : entity work.dpram 162 generic map ( 163 width => 32, 164 depth => MaxFrameSize/4 165 ) 166 port map( 167 addra => InAdd, 168 addrb => OutAdd, 169 clk => clk, 170 dina => RDataLatch, 171 -- douta => 172 doutb => OutData, 173 wea => PushData 174 ); 175 176 abuf: process (clk) 177 begin 178 if rising_edge(clk) then 179 if PushData = '1' then 180 InAdd <= InAdd+1; 181 end if; 182 if popdata = '1' then 183 OutAdd <= OutAdd +1; 184 end if; 185 if Clear = '1' then 186 InAdd <= (others => '0'); 187 OutAdd <= (others => '0'); 188 end if; 189 end if; -- clk 190 if InAdd = OutAdd then 191 FrameBufferEmpty <= '1'; 192 else 193 FrameBufferEmpty <= '0'; 194 end if; 195 end process abuf; 196 197 fiforc: for i in 0 to log2(MaxFrameSize)-1 generate 198 asr16e: SRL16E generic map (x"0000") port map( 199 D => RecvCount(i), 200 CE => PushRC, 201 CLK => clk, 202 A0 => RCPopAdd(0), 203 A1 => RCPopAdd(1), 204 A2 => RCPopAdd(2), 205 A3 => RCPopAdd(3), 206 Q => RCPopData(i) 207 ); 208 end generate; 209 210 fifoerrs: for i in 0 to 1 generate 211 asr16e: SRL16E generic map (x"0000") port map( 212 D => RXErrs(i), 213 CE => PushRC, 214 CLK => clk, 215 A0 => RCPopAdd(0), 216 A1 => RCPopAdd(1), 217 A2 => RCPopAdd(2), 218 A3 => RCPopAdd(3), 219 Q => ErrPopData(i) 220 ); 221 end generate; 222 223 224 arcfifo: process (clk,RCPopData,RFrameCount) -- send counter fifo 225 begin 226 if rising_edge(clk) then 227 if PushRC = '1' and poprc = '0' then 228 if RFrameCount /= 16 then -- a push 229 -- always increment the data counter if not full 230 RFrameCount <= RFrameCount +1; 231 RCPopAdd <= RCPopAdd +1; -- popadd must follow data down shiftreg 232 else 233 RCFIFOError <= '1'; 234 end if; 235 end if; 236 237 if (poprc = '1') and (PushRC = '0') then 238 if RCFIFOEmpty = '0' then -- a pop 239 RFrameCount <= RFrameCount -1; 240 RCPopAdd <= RCPopAdd -1; 241 else 242 RCFIFOError <= '1'; -- pop with no data 243 end if; 244 end if; 245 246 -- if both push and pop are asserted we dont change either counter 247 248 if Clear = '1' then -- a Clear fifo 249 RCPopadd <= (others => '1'); 250 RFrameCount <= (others => '0'); 251 RCFIFOError <= '0'; 252 end if; 253 254 end if; -- clk rise 255 if RFrameCount = 0 then 256 RCFIFOEmpty <= '1'; 257 else 258 RCFIFOEmpty <= '0'; 259 end if; 260 end process arcfifo; 261 262 263 asimpleuartrx: process (clk, loadmode,OldDDSMSB,BitRateDDSAccum,OldDDSMSB, 264 FrameDelayCount,poprc,RCPopData,popdata,OutData, 265 readbitrate,BitRateDDSReg, readmode,ModeReg,RCFIFOError, 266 rxmask,Go,FDGo,ibus) 267 begin 268 if rising_edge(clk) then 269 RXPipe <= RXPipe(0) & rxdata; -- Two stage rx data pipeline to compensate for 270 -- two clock delay from start bit detection to acquire loop startup 271 272 if Go = '1' or FDGo = '1' then 273 BitRateDDSAccum <= BitRateDDSAccum + BitRateDDSReg; 274 if Go = '1' then 275 if SampleTime = '1' then 276 if BitCount = 0 then -- received a char 277 Go <= '0'; 278 if FDGo = '0' then -- first character of a frame 279 RecvCount <= conv_std_logic_vector(1,log2(MaxFrameSize)); 280 else 281 RecvCount <= RecvCount + 1; 282 end if; 283 FDGo <= '1'; 284 FrameDelayCount <= FrameDelay; 285 if RXPipe(1) = '0' then 286 OverRun <= '1'; 287 RXErrs(1) <= '1'; 288 end if; 289 case BytePointer is 290 when "00" => RDataLatch(7 downto 0) <= SRegData; 291 when "01" => RDataLatch(15 downto 8) <= SRegData; 292 when "10" => RDataLatch(23 downto 16) <= SRegData; 293 when "11" => RDataLatch(31 downto 24) <= SRegData; 294 when others => null; 295 end case; 296 if BytePointer = "11" then 297 PushData <= '1'; -- write and advance write data pointer every double word 298 end if; 299 BytePointer <= BytePointer +1; 300 end if; 301 if BitCount = "1001" then -- false start bit check 302 if RXPipe(1) = '1' then 303 Go <= '0'; -- abort receive 304 FalseStart <= '1'; 305 RXErrs(0) <= '1'; 306 end if; 307 end if; 308 SReg <= RXPipe(1) & SReg(9 downto 1); -- right shift = LSb first 309 BitCount <= BitCount -1; 310 end if; -- sampletime 311 end if; 312 if FDGo = '1' then -- framing timeout 313 if DelayTime = '1' then 314 FrameDelayCount <= FrameDelayCount -1; 315 if FrameDelayCount = x"01" then 316 FDGo <= '0'; 317 PushRC <= '1'; 318 ClrRXErrs <= '1'; 319 if BytePointer /= "00" then -- push rest of data if any remaining 320 PushData <= '1'; 321 BytePointer <= "00"; 322 end if; 323 end if; 324 end if; 325 end if; 326 end if; 327 328 if PushData = '1' then 329 PushData <= '0'; 330 end if; 331 332 if PushRC = '1' then 333 PushRC <= '0'; 334 end if; 335 336 if ClrRXErrs = '1' then 337 ClrRXErrs <= '0'; 338 end if; 339 340 ClrRXErrsD <= ClrRXErrs; 341 if ClrRXErrsD = '1' then 342 RXErrs <= "00"; 343 end if; 344 345 if Go = '0' then 346 BitCount <= "1001"; 347 if rxdata = '0' and (rxmask and RXMaskEn) = '0' and RXEnable = '1' then 348 Go <= '1'; -- start bit detection 349 BitRateDDSAccum <= (others => '0'); 350 end if; 351 end if; 352 353 if Clear = '1' then 354 Go <= '0'; 355 FDGo <= '0'; 356 FrameDelayCount <= x"01"; 357 BytePointer <= "00"; 358 end if; 359 360 OldDDSMSB <= DDSMSB; -- for Phase accumulator MSB edge detection 361 362 if loadbitrate = '1' then 363 BitRateDDSReg <= ibus(DDSWidth-1 downto 0); 364 end if; 365 366 if loadmode= '1' and ibus(31) = '0' then 367 ModeReg <= ibus(15 downto 0); 368 end if; 369 370 end if; -- clk 371 372 if loadmode = '1' and ibus(16) = '1' then 373 Clear <= '1'; 374 else 375 Clear <= '0'; 376 end if; 377 378 SampleTime <= (not OldDDSMSB) and DDSMSB; -- sample on rising edge of DDS MSB 379 DelayTime <= OldDDSMSB and (not DDSMSB); 380 381 if FrameDelayCount = x"01" then 382 FrameTimeOut <= '1'; 383 else 384 FrameTimeOut <= '0'; 385 end if; 386 387 obus <= (others => 'Z'); 388 389 if poprc = '1' then 390 obus(log2(maxFrameSize)-1 downto 0) <= RCPopData; 391 obus(13 downto log2(MaxFrameSize)) <= (others => '0'); 392 obus(15 downto 14) <= ErrPopData; 393 obus(31 downto 16) <= (others => '0'); 394 end if; 395 396 if popdata = '1' then 397 obus <= OutData; 398 end if; 399 400 if readbitrate = '1' then 401 obus(DDSWidth-1 downto 0) <= BitRateDDSReg; 402 end if; 403 404 if readmode = '1' then 405 obus(3 downto 0) <= ModeReg(3 downto 0); 406 obus(4) <= RCFIFOError; 407 obus(6) <= rxmask; 408 obus(7) <= Go or FDGo or (not RCFIFOEmpty); 409 obus(15 downto 8) <= ModeReg(15 downto 8); -- frame delay 410 obus(20 downto 16) <= RFrameCount; 411 obus(21) <= not FrameBufferEmpty; 412 obus(31 downto 22) <= (others => '0'); 413 end if; 414 415 end process asimpleuartrx; 416 417 end Behavioral;