vusb_ratematch.v 22.8 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
/*******************************************************************************

-- File Type:    Verilog HDL 
-- Tool Version: VHDL2verilog  v4.4 Tue Sep 19 10:06:32 EDT 2000 SunOS 5.5.1 
-- Input file was: vusb_ratematch
-- Date Created: Tue Jul 16 13:58:37 2002

*******************************************************************************/


`timescale 1 ns / 1 ns // timescale for following modules

// --------------------------------------------------------------------
//  Copyright yyyy VAutomation Inc. Nashua NH USA. All rights reserved.
//  This software is provided under license and contains proprietary
//  and confidential material which is the property of VAutomation Inc.
//  HTTP://www.vautomation.com
// --------------------------------------------------------------------
//  File Name: $Workfile: vusb_ratematch.vhdl$
//  Revision: $Name:  $
//  Description:
//          
//  
//       Describe the inputs and outputs and any requirements or 
//       assumptions.
//       Don't describe in detail what the code does. Assume the reader 
//       is fluent in VHDL. Describe HOW, WHY and any restrictions.
// 
// ---------------------------------------------------------------------
//  This product is licensed to:
//  John Princen of RouteFree
// for use at site(s):
// broadon
// -----------Revision History------------------------------------------
//  $Log: 
//   19   VUSB      1.18        6/27/02 3:20:13 PM     Will Sanborn    Modified 
//         outputs in ratematch block, so OE signal goes active before the data 
//         signals on DPO and DMO.
//   18   VUSB      1.17        6/12/02 2:47:11 PM     Will Sanborn    Fixing 
//         bug WSAN-5B2JR5: VUSB sends 64 byte packets to the host and 
//         occasionally the host doesn't like a packet and does a USB reset. All
//          the bad packets, those before the host does a reset, exhibited a 
//         long EOP. Upon closer inspection, the output enable signal to the 
//         transciever goes away before driving the dplus line high. This would 
//         cause the host to see a long/invalid EOP.  
//   17   VUSB      1.16        4/11/02 2:49:11 PM     Patrick Koran   all 
//         checked in from pats pc, week of Starteam upgrade 4.6 to 5.1
//   16   VUSB      1.15        2/27/02 10:46:45 AM    Tom Frechette   Removed 
//         low_speed from sensitivity list.
//   15   VUSB      1.14        2/11/02 3:39:19 PM     Tom Frechette   making 
//         clocks and resets uniform.
//   14   VUSB      1.13        2/11/02 2:45:55 PM     Tom Frechette   Still 
//         fixing resets.
//   13   VUSB      1.12        2/11/02 2:15:38 PM     Tom Frechette   Fixing 
//         resets for changereset script.
//   12   VUSB      1.11        9/17/01 4:20:04 PM     Monika Leary    Fixed bug
//          which caused the oe to be disabled to early
//   11   VUSB      1.10        8/23/01 9:49:19 AM     Tom Frechette   
//   10   VUSB      1.9         8/7/01 10:00:33 AM     Monika Leary    Added 
//         some comments
//   9    VUSB      1.8         8/2/01 4:00:50 PM      Monika Leary    Fixed bug
//          in previous checkin
//   8    VUSB      1.7         7/31/01 11:26:38 AM    Monika Leary    Changed 
//         transmit clock enable generation so it will work for low speed
//   7    VUSB      1.6         7/24/01 5:07:17 PM     Monika Leary    Small 
//         change to get rid of a synthesis warning
//   6    VUSB      1.5         6/22/01 9:07:07 AM     Tom Frechette   Changed 
//         name of config package
//   5    VUSB      1.4         6/21/01 10:00:21 AM    Tom Frechette   Changed 
//         the name.
//   4    VUSB      1.3         6/21/01 9:52:11 AM     Tom Frechette   
//   3    VUSB      1.2         5/25/01 1:39:30 PM     Monika Leary    Code 
//         cleanup
//   2    VUSB      1.1         5/16/01 2:52:26 PM     Monika Leary    
//   1    VUSB      1.0         5/15/01 3:45:37 PM     Monika Leary    
//  $
//  $NoKeywords$
// ---------------------------------------------------------------------
// ------------------------------------------------------------------------------
//  Copyright 1995 VAutomation Inc. Nashua NH (603)882-2282 ALL RIGHTS RESERVED.
//  This software is provided under license and contains proprietary and 
//  confidential material which is the property of VAutomation Inc.
// 
//  File: vusb_cfg.vhd	USB Configuration file.
// 
//  Revision: $Revision: 1.1.1.1 $
// 
//  Description: A Package file for the usb core that defines global usb constants
//      that contol how the VUSB core is synthesised.
// 
// ---------------------------------------------------------------------------
//  This product is licensed to:
//  $name$ of $company$
//  for use at site(s): 
//  $site$
// ------------------------------------------------------------------------------
//  Revision History
//  $Log: 
//   32   VUSB      1.31        7/5/02 9:15:50 AM      Chris Kolb      Moved 
//         VUSB build configruation Revision constant to vusb_cfg, and updated 
//         the rev number to 3.0.
//   31   VUSB      1.30        4/11/02 2:49:09 PM     Patrick Koran   all 
//         checked in from pats pc, week of Starteam upgrade 4.6 to 5.1
//   30   VUSB      1.29        3/18/02 10:52:11 AM    Tom Frechette   Changed 
//         IRQ_NUM default to 0x0.
//   29   VUSB      1.28        3/15/02 2:39:08 PM     Tom Frechette   Added 
//         Interupt info into add_info register.
//   28   VUSB      1.27        2/7/02 4:49:00 PM      Tom Frechette   Removed 
//         sync config variable.
//   27   VUSB      1.26        8/23/01 9:48:58 AM     Tom Frechette   
//   26   VUSB      1.25        7/25/01 3:41:35 PM     Tom Frechette   Changed 
//         FIFO Parameter Names.
//   25   VUSB      1.24        7/10/01 3:03:41 PM     Tom Frechette   Moved 
//         HOST comment for verilog.
//   24   VUSB      1.23        7/6/01 7:44:00 AM      Tom Frechette   Added 
//         host comments around host constant to make it look like vusb_sie.
//   23   VUSB      1.22        7/6/01 7:34:33 AM      Tom Frechette   Added 
//         device constant comment for ARC.
//   22   VUSB      1.21        7/3/01 4:42:08 PM      Tom Frechette   Changed 
//         mode to a constant in vusb_cfg.
//   21   VUSB      1.20        6/22/01 3:09:48 PM     Tom Frechette   Changed 
//         endpoint number.
//   20   VUSB      1.19        6/21/01 9:59:56 AM     Tom Frechette   Changed 
//         the name and added fifo constants
//   19   VUSB      1.18        6/21/01 9:51:24 AM     Tom Frechette   
//   18   VUSB      1.17        5/25/01 10:25:08 AM    Monika Leary    Set 
//         synchronous reset constant to '1'
//   17   VUSB      1.16        5/17/01 2:52:48 PM     Monika Leary    Added 
//         USE_SYNC_RESET constant
//   16   VUSB      1.15        12/14/00 8:42:11 AM    Christopher Meyers RCS 
//         Keyword To StarTeam Keyword Translation
//   15   VUSB      1.14        12/13/00 7:58:39 PM    Chris Kolb      Removed 
//         the HOST_WITHOUT_HUB constant. This control is now a Endpt0 control 
//         register bit in up_int.vhd.
//   14   VUSB      1.13        12/13/00 7:58:31 PM    Gregory Recupero Removed 
//         ^M's
//   13   VUSB      1.12        12/13/00 7:58:26 PM    Mark Pettigrew  
//         ulogicified source - no functional changes
//   12   VUSB      1.11        12/13/00 7:58:19 PM    Chris Kolb      Change 
//         type of HOST_WITHOUT_HUB from std_logic to integer so that it could 
//         be used to initialize a _synopsysTM(TM) compatible generic.
//   11   VUSB      1.10        12/13/00 7:58:14 PM    Chris Kolb      Set 
//         constant to support Host to Low Speed device thru a hub.
//   10   VUSB      1.9         12/13/00 7:58:07 PM    Chris Kolb      Changed 
//         LOW_SPEED_DEV constant to type integer to support generics.
//   9    VUSB      1.8         12/13/00 7:57:58 PM    Christopher Meyers 
//         removed ASIC_IMPLEMENTATION constant
//   8    VUSB      1.7         12/13/00 7:57:46 PM    Chris Kolb      Remove 
//         ^M's. No functional changes.
//   7    VUSB      1.6         12/13/00 7:57:39 PM    Chris Kolb      Added 
//         HOST_WITHOUT_HUB constant to support new code in the DPLLNRZI.
//   6    VUSB      1.5         12/13/00 7:57:19 PM    Chris Kolb      Turned 
//         host mode back on.
//   5    VUSB      1.4         12/13/00 7:57:12 PM    Chris Kolb      Reverted 
//         to device only implementation.
//   4    VUSB      1.3         12/13/00 7:57:08 PM    Chris Kolb      Added 
//         revision string.
//   3    VUSB      1.2         12/13/00 7:57:03 PM    Chris Kolb      Enabled 
//         implementation of embedded host functions.
//   2    VUSB      1.1         12/13/00 7:56:58 PM    Chris Kolb      Added 
//         IMPLEMENT_EMBEDED_HOST constant.
//   1    VUSB      1.0         12/13/00 7:56:51 PM    Chris Kolb      initial 
//         revision
//  $
// 
// 
// ------------------------------------------------------------------------------
module vusb_ratematch (usb_clk48,
   usb_rst48,
   usb_rst48_a,
   clken_dpll,
   clk,
   rst,
   rst_a,
   low_speed_en,
   sys_clken12,
   dpll_data,
   dpll_eop,
   dpll_rcv,
   dpll_se0,
   sie_clk_en,
   sie_data,
   sie_eop,
   sie_rcv,
   sie_se0,
   sie_dpo,
   sie_dmo,
   sie_usboe,
   sie_usboe_early,
   xcvr_dpo,
   xcvr_dmo,
   xcvr_usboe);

 		// file containing translation of VHDL package 'vusb_cfg' 

parameter lsdev = 0;
`include "vusb_cfg.v"
input   usb_clk48; //  high speed clock
input   usb_rst48; 
input   usb_rst48_a; 
input   clken_dpll; //  clock enable from the dpll
input   clk; //  system clock
input   rst; //  synchronous system reset
input   rst_a; //  asynchronous system reset
input   low_speed_en; //  USB speed control
output   sys_clken12; 
input   dpll_data; //  NRZ serial data from dpll
input   dpll_eop; //  End of Packet detected from dpll
input   dpll_rcv; //  Synchronized jstate signal from dpll
input   dpll_se0; //  Single ended zero from dpll
output   sie_clk_en; 
output   sie_data; //  NRZ seral data out sync to clk_sys
output   sie_eop; //  End of packet sync to clk_sys
output   sie_rcv; //  jstate signal sync to clk_sys
output   sie_se0; //  Single ended zero sync to clk_sys
input   sie_dpo; 
input   sie_dmo; 
input   sie_usboe; 
input   sie_usboe_early; 
output   xcvr_dpo; 
output   xcvr_dmo; 
output   xcvr_usboe; 
wire    sys_clken12; 
wire    sie_clk_en; 
wire    sie_data; 
wire    sie_eop; 
wire    sie_rcv; 
//  inputs from the sie
wire    sie_se0; 
reg     xcvr_dpo; 
reg     xcvr_dmo; 
wire    xcvr_usboe; 
reg     [4:0] clk12_cnt; 
reg     clken_dpll_tog_r; 
wire    clken12_tx; 
reg     [4:0] clken12_tx_phase; 
//   signal clken12_tx : std_ulogic;
//   signal clken12_tx_phase : std_ulogic_vector(1 downto 0);
reg     dpll_data_0_r; 
reg     dpll_eop_0_r; 
reg     dpll_rcv_0_r; 
reg     dpll_se0_0_r; 
reg     dpll_data_1_r; 
reg     dpll_eop_1_r; 
reg     dpll_rcv_1_r; 
reg     dpll_se0_1_r; 
wire    low_speed; 
reg     sie_clken_tog_r; 
reg     sie_usboe_0_r; 
reg     sie_usboe_1_r; 
reg     sie_usboe_early_r1; 
reg     sie_usboe_early_r2; 
reg     sie_dpo_0_r; 
reg     sie_dmo_0_r; 
reg     sie_dpo_1_r; 
reg     sie_dmo_1_r; 
reg     sys_clk12_fe_r_sync; 
reg     sys_clk12_r2; 
reg     sys_clk12_r3; 
reg     sys_dpll_tog_fe_r_sync; 
reg     sys_dpll_tog_r2; 
reg     sys_dpll_tog_r3; 
wire    sys_fifo_valid; 
reg     sys_fifo_valid_r; 
reg     tx_fifo_rd_tog_r; 
reg     tx_enable_fe_r_sync; 
reg     tx_enable_r2; 
reg     tx_enable_r3; 
wire    tx_enable_re; 
reg     xcvr_usboe_i; 
// ---------------------------------------------------------------------------
//  RX ratematch - A two-deep fifo is used to synchronize the rx inputs to
//  the system clock. 
// ---------------------------------------------------------------------------
//  A toggle bit is used as an address into the two deep fifo

always @(posedge usb_clk48 or posedge usb_rst48_a)
   begin : dpll_tog_proc
   if (usb_rst48_a == 1'b 1)
      begin
      clken_dpll_tog_r <= 1'b 0;	
      end
   else
      begin
      if (usb_rst48 == 1'b 1)
         begin
         clken_dpll_tog_r <= 1'b 0;	
         end
      else if (clken_dpll == 1'b 1 )
         begin
         clken_dpll_tog_r <= ~clken_dpll_tog_r;	
         end
      end
   end
//  Write side the fifo
always @(posedge usb_clk48 or posedge usb_rst48_a)
   begin : rx_fifo_wr_proc
   if (usb_rst48_a == 1'b 1)
      begin
      dpll_data_0_r <= 1'b 0;	
      dpll_eop_0_r <= 1'b 0;	
      dpll_rcv_0_r <= 1'b 0;	
      dpll_se0_0_r <= 1'b 0;	
      dpll_data_1_r <= 1'b 0;	
      dpll_eop_1_r <= 1'b 0;	
      dpll_rcv_1_r <= 1'b 0;	
      dpll_se0_1_r <= 1'b 0;	
      end
   else
      begin
      if (usb_rst48 == 1'b 1)
         begin
         dpll_data_0_r <= 1'b 0;	
         dpll_eop_0_r <= 1'b 0;	
         dpll_rcv_0_r <= 1'b 0;	
         dpll_se0_0_r <= 1'b 0;	
         dpll_data_1_r <= 1'b 0;	
         dpll_eop_1_r <= 1'b 0;	
         dpll_rcv_1_r <= 1'b 0;	
         dpll_se0_1_r <= 1'b 0;	
         end
      else
         begin
         if (clken_dpll == 1'b 1 & clken_dpll_tog_r == 1'b 0)
            begin
            dpll_data_0_r <= dpll_data;	
            dpll_eop_0_r <= dpll_eop;	
            dpll_rcv_0_r <= dpll_rcv;	
            dpll_se0_0_r <= dpll_se0;	
            end
         if (clken_dpll == 1'b 1 & clken_dpll_tog_r == 1'b 1)
            begin
            dpll_data_1_r <= dpll_data;	
            dpll_eop_1_r <= dpll_eop;	
            dpll_rcv_1_r <= dpll_rcv;	
            dpll_se0_1_r <= dpll_se0;	
            end
         end
      end
   end
//  Synchronize the dpll_tog signal to the clk domain
//  register on falling edge for first stage
always @(negedge clk or posedge rst_a)
   begin : sys_dpll_tog_fe_proc
   if (rst_a == 1'b 1)
      begin
      sys_dpll_tog_fe_r_sync <= 1'b 0;	
      end
   else
      begin
      if (rst == 1'b 1)
         begin
         sys_dpll_tog_fe_r_sync <= 1'b 0;	
         end
      else
         begin
         sys_dpll_tog_fe_r_sync <= clken_dpll_tog_r;	
         end
      end
   end
//  once it's registered on the rising edge it should
//  be save to use
always @(posedge clk or posedge rst_a)
   begin : sys_dpll_tog_proc
   if (rst_a == 1'b 1)
      begin
      sys_dpll_tog_r3 <= 1'b 0;	
      sys_dpll_tog_r2 <= 1'b 0;	
      end
   else
      begin
      if (rst == 1'b 1)
         begin
         sys_dpll_tog_r3 <= 1'b 0;	
         sys_dpll_tog_r2 <= 1'b 0;	
         end
      else
         begin
         sys_dpll_tog_r3 <= sys_dpll_tog_r2;	
         sys_dpll_tog_r2 <= sys_dpll_tog_fe_r_sync;	
         end
      end
   end

assign sys_fifo_valid = sys_dpll_tog_r2 ^ sys_dpll_tog_r3; 
assign sie_clk_en = sys_fifo_valid; 
//  Output side of the fifo
assign sie_data = sys_dpll_tog_r2 == 1'b 1 ? dpll_data_0_r : 
	dpll_data_1_r; 
assign sie_eop = sys_dpll_tog_r2 == 1'b 1 ? dpll_eop_0_r : 
	dpll_eop_1_r; 
assign sie_rcv = sys_dpll_tog_r2 == 1'b 1 ? dpll_rcv_0_r : 
	dpll_rcv_1_r; 
assign sie_se0 = sys_dpll_tog_r2 == 1'b 1 ? dpll_se0_0_r : 
	dpll_se0_1_r; 
// ---------------------------------------------------------------------------
//  Transmit rate match
// ---------------------------------------------------------------------------
//  a toggle bit which acts as the counter for a two-deep fifo
always @(posedge clk or posedge rst_a)
   begin : clken_tog_proc
   if (rst_a == 1'b 1)
      begin
      sys_fifo_valid_r <= 1'b 0;	
      sie_clken_tog_r <= 1'b 0;	
      end
   else
      begin
      if (rst == 1'b 1)
         begin
         sys_fifo_valid_r <= 1'b 0;	
         sie_clken_tog_r <= 1'b 0;	
         end
      else
         begin
         sys_fifo_valid_r <= sys_fifo_valid;	
         if ((sie_usboe == 1'b 1 | sie_usboe_0_r == 1'b 1 | 
	sie_usboe_1_r == 1'b 1) & sys_fifo_valid == 1'b 1)
            begin
            sie_clken_tog_r <= ~sie_clken_tog_r;	
            end
         else if (sie_usboe == 1'b 0 & sie_usboe_0_r == 1'b 0 & 
	sie_usboe_1_r == 1'b 0 )
            begin
            sie_clken_tog_r <= 1'b 0;	
            end
         end
      end
   end
//  Write into the fifo
always @(posedge clk or posedge rst_a)
   begin : tx_fifo_wr_proc
   if (rst_a == 1'b 1)
      begin
      sie_usboe_0_r <= 1'b 0;	
      sie_dpo_0_r <= 1'b 0;	
      sie_dmo_0_r <= 1'b 0;	
      sie_usboe_1_r <= 1'b 0;	
      sie_dpo_1_r <= 1'b 0;	
      sie_dmo_1_r <= 1'b 0;	
      end
   else
      begin
      if (rst == 1'b 1)
         begin
         sie_usboe_0_r <= 1'b 0;	
         sie_dpo_0_r <= 1'b 0;	
         sie_dmo_0_r <= 1'b 0;	
         sie_usboe_1_r <= 1'b 0;	
         sie_dpo_1_r <= 1'b 0;	
         sie_dmo_1_r <= 1'b 0;	
         end
      else
         begin
         if (sys_fifo_valid_r == 1'b 1 & sie_clken_tog_r == 1'b 0)
            begin
            sie_usboe_0_r <= sie_usboe;	
            sie_dpo_0_r <= sie_dpo;	
            sie_dmo_0_r <= sie_dmo;	
            end
         if (sys_fifo_valid_r == 1'b 1 & sie_clken_tog_r == 1'b 1)
            begin
            sie_usboe_1_r <= sie_usboe;	
            sie_dpo_1_r <= sie_dpo;	
            sie_dmo_1_r <= sie_dmo;	
            end
         end
      end
   end
//  synchronize the toggle bit to generate a start bit
always @(negedge usb_clk48 or posedge usb_rst48_a)
   begin : clken_tog_fe_proc
   if (usb_rst48_a == 1'b 1)
      begin
      tx_enable_fe_r_sync <= 1'b 0;	
      end
   else
      begin
      if (usb_rst48 == 1'b 1)
         begin
         tx_enable_fe_r_sync <= 1'b 0;	
         end
      else
         begin
         tx_enable_fe_r_sync <= sie_usboe;	
         end
      end
   end
//  second stage of synchronization
always @(posedge usb_clk48 or posedge usb_rst48_a)
   begin : clken_tog_sync_proc
   if (usb_rst48_a == 1'b 1)
      begin
      tx_enable_r2 <= 1'b 0;	
      tx_enable_r3 <= 1'b 0;	
      end
   else
      begin
      if (usb_rst48 == 1'b 1)
         begin
         tx_enable_r2 <= 1'b 0;	
         tx_enable_r3 <= 1'b 0;	
         end
      else
         begin
         tx_enable_r2 <= tx_enable_fe_r_sync;	
         tx_enable_r3 <= tx_enable_r2;	
         end
      end
   end

assign tx_enable_re = tx_enable_r2 & ~tx_enable_r3; 
//  Generate the read address
always @(posedge usb_clk48 or posedge usb_rst48_a)
   begin : tx_fifo_rd_tog_proc
   if (usb_rst48_a == 1'b 1)
      begin
      tx_fifo_rd_tog_r <= 1'b 0;	
      end
   else
      begin
      if (usb_rst48 == 1'b 1)
         begin
         tx_fifo_rd_tog_r <= 1'b 0;	
         end
      else if (tx_enable_re == 1'b 1 )
         begin
         tx_fifo_rd_tog_r <= 1'b 0;	
         end
      else if (clken12_tx == 1'b 1 )
         begin
         tx_fifo_rd_tog_r <= ~tx_fifo_rd_tog_r;	
         end
      end
   end
//  Register outputs of the fifo on the
//  48 mhz clock
always @(posedge usb_clk48 or posedge usb_rst48_a)
   begin : tx_fifo_out_proc
   if (usb_rst48_a == 1'b 1)
      begin
      xcvr_dpo <= ~low_speed;	
      xcvr_dmo <= low_speed;	
      xcvr_usboe_i <= 1'b 0;	
      end
   else
      begin
      if (usb_rst48 == 1'b 1)
         begin
         xcvr_usboe_i <= 1'b 0;	
         xcvr_dpo <= ~low_speed;	
         xcvr_dmo <= low_speed;	
         end
      else
         begin
         if (clken12_tx == 1'b 1 & tx_fifo_rd_tog_r == 1'b 1)
            begin
            xcvr_usboe_i <= sie_usboe_1_r;	
            xcvr_dpo <= sie_dpo_1_r;	
            xcvr_dmo <= sie_dmo_1_r;	
            end
         else if (clken12_tx == 1'b 1 )
            begin
            xcvr_usboe_i <= sie_usboe_0_r;	
            xcvr_dpo <= sie_dpo_0_r;	
            xcvr_dmo <= sie_dmo_0_r;	
            end
         end
      end
   end
//  sie_usboe_early is used to enable usboe before data output on dpo/dmo
assign xcvr_usboe = xcvr_usboe_i | sie_usboe_early_r2; 
assign low_speed = lsdev == 1 ? 1'b 1 : 
	1'b 0; 
//  synchronize sie_usboe_early to 48 mhz clock
always @(posedge usb_clk48 or posedge usb_rst48_a)
   begin : sie_usboe_early_sync_proc
   if (usb_rst48_a == 1'b 1)
      begin
      sie_usboe_early_r2 <= 1'b 0;	
      sie_usboe_early_r1 <= 1'b 0;	
      end
   else
      begin
      if (usb_rst48 == 1'b 1)
         begin
         sie_usboe_early_r2 <= 1'b 0;	
         sie_usboe_early_r1 <= 1'b 0;	
         end
      else
         begin
         sie_usboe_early_r2 <= sie_usboe_early_r1;	
         sie_usboe_early_r1 <= sie_usboe_early;	
         end
      end
   end
// ---------------------------------------------------------------------------
//  Make a 12 mhz clock enable synchronized to the sys clock
//  The clock enable is 12mhz in high speed mode and 1.5mhz in low speed mode.
//  When the sie starts transmitting somthing (usb_oe goes high), the phase
//  of the 48mhz clock is selected and the clock enable starts running.  The
//  clock enable stays low when nothing is being transmitted.
// ---------------------------------------------------------------------------
always @(posedge usb_clk48 or posedge usb_rst48_a)
   begin : div4_proc
   if (usb_rst48_a == 1'b 1)
      begin
      clk12_cnt <= {5{1'b 0}};	
      clken12_tx_phase <= {5{1'b 0}};	
      end
   else
      begin
      if (usb_rst48 == 1'b 1)
         begin
         clk12_cnt <= {5{1'b 0}};	
         clken12_tx_phase <= {5{1'b 0}};	
         end
      else
         begin
         if (low_speed_en == 1'b 1)
            begin
            clk12_cnt <= clk12_cnt + 1'b 1;	
            end
         else
            begin
            clk12_cnt[4:2] <= 3'b 000;	
            clk12_cnt[1:0] <= clk12_cnt[1:0] + 1'b 1;	
//  select the phase of the 48mhz clock on the beginning of a transmit
//  this is required to minimize the delay of the synchronization
            end
         if (tx_enable_re == 1'b 1)
            begin
            if (low_speed_en == 1'b 1)
               begin
               clken12_tx_phase <= clk12_cnt;	
               end
            else
               begin
               clken12_tx_phase[4:2] <= 3'b 000;	
               clken12_tx_phase[1:0] <= clk12_cnt[1:0];	
               end
            end
         end
      end
   end
//  Generate the clock enable for the tx fifo
assign clken12_tx = (tx_enable_r3 == 1'b 1 | xcvr_usboe_i == 1'b 1) & 
	clk12_cnt == clken12_tx_phase ? 1'b 1 : 
	1'b 0; 
//  Synchronize the 12mhz clock to the system clock
always @(negedge clk or posedge rst_a)
   begin : clk12_sync_fe_proc
   if (rst_a == 1'b 1)
      begin
      sys_clk12_fe_r_sync <= 1'b 0;	
      end
   else
      begin
      if (rst == 1'b 1)
         begin
         sys_clk12_fe_r_sync <= 1'b 0;	
         end
      else
         begin
         sys_clk12_fe_r_sync <= clk12_cnt[1];	
         end
      end
   end
//  second stage of synchronization
always @(posedge clk or posedge rst_a)
   begin : clk12_sync_proc
   if (rst_a == 1'b 1)
      begin
      sys_clk12_r3 <= 1'b 0;	
      sys_clk12_r2 <= 1'b 0;	
      end
   else
      begin
      if (rst == 1'b 1)
         begin
         sys_clk12_r3 <= 1'b 0;	
         sys_clk12_r2 <= 1'b 0;	
         end
      else
         begin
         sys_clk12_r3 <= sys_clk12_r2;	
         sys_clk12_r2 <= sys_clk12_fe_r_sync;	
         end
      end
   end

assign sys_clken12 = sys_clk12_r2 & ~sys_clk12_r3; 
//  of vusb_ratematch

endmodule // module vusb_ratematch