| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 | //// Serial port "snoop" of the console (otherwise sent via USB.)//// The only receive support is BREAK.//// The transmission rate is fixed to 1 Mbps.//// If the output FIFO is full, an output signal is asserted, which// is expected to be used together with DTR to provide blocking I/O// if desired.//module serial (	    input 	rst_n,	    input 	clk,	    input 	tx_valid,	    input [7:0] tx_data,	    input 	tty_rx,	    output 	tty_tx,	    output reg	rx_break,	    output 	tx_full	    );   `include "functions.sv"	// For ModelSim   //   // Baud rate generator; produces a clock enable synchronous   // with clk.  This is based on a numerically controlled oscillator   // (NCO); the baudrate is given as a binary fraction of the input   // clock rate divided by the oversampling rate (16); for practical   // reasons represented minus one LSB so 0x0.ffffff -> 1   // and 0 -> 0x0.000001.   //   // The term "divisor" here is probably misleading, since it is   // actually a fixed-point *multiplier* which is <= 1.   //   parameter [31:0]	BAUDRATE = 1000000;   parameter [31:0]	TTY_CLK  = 84000000;   parameter		NCO_BITS = 24;   parameter            BREAK_BITS = 19; // 2^19/(BAUDRATE*16) ~ 33 ms   reg  [NCO_BITS-1:0]  divisor			= round_div(BAUDRATE << NCO_BITS, TTY_CLK >> 4) - 1'b1;   reg  [NCO_BITS-1:0]  nco_q;   reg			tty_clk_en; // tty clock tick (clock enable)   always @(posedge clk)	{ tty_clk_en, nco_q } <= nco_q + divisor + 1'b1;   //   // Tx FIFO   //   reg  tx_rdack;   wire tx_wrreq;   wire tx_rdempty;   wire [7:0] tx_out_data;   reg 	      tx_valid_q;   always @(negedge rst_n or posedge clk)     if (~rst_n)       tx_valid_q <= 1'b0;     else       tx_valid_q <= tx_valid;   fifo txfifo (		.aclr ( ~rst_n ),		.clock ( clk ),		.data ( tx_data ),		.rdreq ( tx_rdack ),		.sclr ( 1'b0 ),	// Flush FIFO command		.wrreq ( tx_valid & ~tx_valid_q ),		.empty ( tx_rdempty ),		.full ( tx_full ),		.q ( tx_out_data ),		.usedw ( )		);   //   // Transmitter   //   reg [3:0]  tx_phase;   reg [3:0]  tx_bits;   reg [9:0]  tx_sr = ~10'b0;		// Shift register   assign tty_tx = tx_sr[0];   always @(negedge rst_n or posedge clk)     if (~rst_n)       begin	  tx_phase <= 4'h0;	  tx_bits  <= 4'd0;	  tx_sr    <= ~10'b0;	// Line idle	  tx_rdack <= 1'b0;       end     else       begin	  tx_rdack <= 1'b0;	  if ( tty_clk_en )	    begin	       tx_phase <= tx_phase + 1'b1;	       if (tx_phase == 4'hF)		 begin		    tx_sr[8:0] <= tx_sr[9:1];		    tx_sr[9]   <= 1'b1; // Stop bit/idle		    if (tx_bits == 4'd0)		      begin			 if ( ~tx_rdempty )			   begin			      tx_sr[9:2] <= tx_out_data;			      tx_sr[1]   <= 1'b0; // Start bit			      // 10 = start bit + data + stop bit			      tx_bits    <= 4'd10;			      tx_rdack   <= 1'b1; // Remove from FIFO			   end		      end		    else		      begin			 tx_bits <= tx_bits - 1'b1;		      end // else: !if(tx_bits == 4'd0)		 end // if (tx_phase == 4'hF)	    end // if ( tty_clk_en )       end // else: !if(~rst_n)   //   // BREAK detect   //   reg  [BREAK_BITS-1:0] rx_break_ctr;   wire   [BREAK_BITS:0] rx_break_ctr_next = rx_break_ctr + 1'b1;      always @(negedge rst_n or posedge clk)     if (~rst_n)       begin	  rx_break_ctr <= 'b0;	  rx_break     <= 1'b0;       end     else       begin	  if ( tty_clk_en )	    begin	       if ( tty_rx )		 begin		    // Rx high = not a break		    rx_break_ctr <= 'b0;		    rx_break     <= 1'b0;		 end	       else		 begin		    rx_break_ctr <= rx_break_ctr_next[BREAK_BITS-1:0];		    rx_break     <= rx_break | rx_break_ctr_next[BREAK_BITS];		 end // else: !if(tty_rxd)	    end // if ( tty_clk_en )       end // else: !if(~rst_n)   endmodule // serial
 |