serial.sv 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. //
  2. // Serial port "snoop" of the console (otherwise sent via USB.)
  3. //
  4. // The only receive support is BREAK.
  5. //
  6. // The transmission rate is fixed to 1 Mbps.
  7. //
  8. // If the output FIFO is full, an output signal is asserted, which
  9. // is expected to be used together with DTR to provide blocking I/O
  10. // if desired.
  11. //
  12. module serial (
  13. input rst_n,
  14. input clk,
  15. input tx_valid,
  16. input [7:0] tx_data,
  17. input tty_rx,
  18. output tty_tx,
  19. output reg rx_break,
  20. output tx_full
  21. );
  22. `include "functions.sv" // For ModelSim
  23. //
  24. // Baud rate generator; produces a clock enable synchronous
  25. // with clk. This is based on a numerically controlled oscillator
  26. // (NCO); the baudrate is given as a binary fraction of the input
  27. // clock rate divided by the oversampling rate (16); for practical
  28. // reasons represented minus one LSB so 0x0.ffffff -> 1
  29. // and 0 -> 0x0.000001.
  30. //
  31. // The term "divisor" here is probably misleading, since it is
  32. // actually a fixed-point *multiplier* which is <= 1.
  33. //
  34. parameter [31:0] BAUDRATE = 921600;
  35. parameter [31:0] TTY_CLK = 84000000;
  36. parameter NCO_BITS = 24;
  37. parameter BREAK_BITS = 19; // 2^19/(BAUDRATE*16) ~ 33 ms
  38. reg [NCO_BITS-1:0] divisor
  39. = round_div(BAUDRATE << NCO_BITS, TTY_CLK >> 4) - 1'b1;
  40. reg [NCO_BITS-1:0] nco_q;
  41. reg tty_clk_en; // tty clock tick (clock enable)
  42. always @(posedge clk)
  43. { tty_clk_en, nco_q } <= nco_q + divisor + 1'b1;
  44. //
  45. // Tx FIFO
  46. //
  47. reg tx_rdack;
  48. wire tx_wrreq;
  49. wire tx_rdempty;
  50. wire [7:0] tx_out_data;
  51. reg tx_valid_q;
  52. always @(negedge rst_n or posedge clk)
  53. if (~rst_n)
  54. tx_valid_q <= 1'b0;
  55. else
  56. tx_valid_q <= tx_valid;
  57. fifo txfifo (
  58. .aclr ( ~rst_n ),
  59. .clock ( clk ),
  60. .data ( tx_data ),
  61. .rdreq ( tx_rdack ),
  62. .sclr ( 1'b0 ), // Flush FIFO command
  63. .wrreq ( tx_valid & ~tx_valid_q ),
  64. .empty ( tx_rdempty ),
  65. .full ( tx_full ),
  66. .q ( tx_out_data ),
  67. .usedw ( )
  68. );
  69. //
  70. // Transmitter
  71. //
  72. reg [3:0] tx_phase;
  73. reg [3:0] tx_bits;
  74. reg [9:0] tx_sr = ~10'b0; // Shift register
  75. assign tty_tx = tx_sr[0];
  76. always @(negedge rst_n or posedge clk)
  77. if (~rst_n)
  78. begin
  79. tx_phase <= 4'h0;
  80. tx_bits <= 4'd0;
  81. tx_sr <= ~10'b0; // Line idle
  82. tx_rdack <= 1'b0;
  83. end
  84. else
  85. begin
  86. tx_rdack <= 1'b0;
  87. if ( tty_clk_en )
  88. begin
  89. tx_phase <= tx_phase + 1'b1;
  90. if (tx_phase == 4'hF)
  91. begin
  92. tx_sr[8:0] <= tx_sr[9:1];
  93. tx_sr[9] <= 1'b1; // Stop bit/idle
  94. if (tx_bits == 4'd0)
  95. begin
  96. if ( ~tx_rdempty )
  97. begin
  98. tx_sr[9:2] <= tx_out_data;
  99. tx_sr[1] <= 1'b0; // Start bit
  100. // 10 = start bit + data + stop bit
  101. tx_bits <= 4'd10;
  102. tx_rdack <= 1'b1; // Remove from FIFO
  103. end
  104. end
  105. else
  106. begin
  107. tx_bits <= tx_bits - 1'b1;
  108. end // else: !if(tx_bits == 4'd0)
  109. end // if (tx_phase == 4'hF)
  110. end // if ( tty_clk_en )
  111. end // else: !if(~rst_n)
  112. //
  113. // BREAK detect
  114. //
  115. reg [BREAK_BITS-1:0] rx_break_ctr;
  116. wire [BREAK_BITS:0] rx_break_ctr_next = rx_break_ctr + 1'b1;
  117. always @(negedge rst_n or posedge clk)
  118. if (~rst_n)
  119. begin
  120. rx_break_ctr <= 'b0;
  121. rx_break <= 1'b0;
  122. end
  123. else
  124. begin
  125. if ( tty_clk_en )
  126. begin
  127. if ( tty_rx )
  128. begin
  129. // Rx high = not a break
  130. rx_break_ctr <= 'b0;
  131. rx_break <= 1'b0;
  132. end
  133. else
  134. begin
  135. rx_break_ctr <= rx_break_ctr_next[BREAK_BITS-1:0];
  136. rx_break <= rx_break | rx_break_ctr_next[BREAK_BITS];
  137. end // else: !if(tty_rxd)
  138. end // if ( tty_clk_en )
  139. end // else: !if(~rst_n)
  140. endmodule // serial