|  | @@ -45,11 +45,11 @@
 | 
	
		
			
				|  |  |  //        11:9 - receive FIFO low watermark   (resets to 1/4)
 | 
	
		
			
				|  |  |  //       15:13 - receive FIFO high watermark  (resets to 3/4)
 | 
	
		
			
				|  |  |  // 2 - RO - status register (some bits W1C)
 | 
	
		
			
				|  |  | -//           0 - transmit FIFO empty
 | 
	
		
			
				|  |  | +//           0 - transmit FIFO empty (write 1 to flush Tx data)
 | 
	
		
			
				|  |  |  //           1 - transmit FIFO <= low watermark
 | 
	
		
			
				|  |  |  //           2 - transmit FIFO >= high watermark
 | 
	
		
			
				|  |  |  //           3 - transmit FIFO full
 | 
	
		
			
				|  |  | -//           4 - receive FIFO empty
 | 
	
		
			
				|  |  | +//           4 - receive FIFO empty (write 1 to flush Rx data)
 | 
	
		
			
				|  |  |  //           5 - receive FIFO <= low watermark
 | 
	
		
			
				|  |  |  //           6 - receive FIFO >= high watermark
 | 
	
		
			
				|  |  |  //           7 - receive FIFO full
 | 
	
	
		
			
				|  | @@ -98,11 +98,16 @@ module usb_cdc_channel
 | 
	
		
			
				|  |  |     input	 start_of_frame_s
 | 
	
		
			
				|  |  |     );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   localparam fifo_size   = 1024;
 | 
	
		
			
				|  |  | -   localparam fifo_bits   = $clog2(fifo_size);
 | 
	
		
			
				|  |  | +   localparam fifo_bits   = 10;
 | 
	
		
			
				|  |  | +   localparam fifo_size   = 1 << fifo_bits;
 | 
	
		
			
				|  |  |     localparam packet_bits = 6;
 | 
	
		
			
				|  |  |     localparam packet_size = 1 << packet_bits;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +   // Control line status in the USB domain
 | 
	
		
			
				|  |  | +   reg [1:0]   control_lines_q;
 | 
	
		
			
				|  |  | +   wire        inport_dtr_w = control_lines_q[0];
 | 
	
		
			
				|  |  | +   wire        inport_rts_w = control_lines_q[1];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |     // Up to four bits per watermark, but all are not necessarily
 | 
	
		
			
				|  |  |     // implemented
 | 
	
		
			
				|  |  |     localparam water_bits  = 3;
 | 
	
	
		
			
				|  | @@ -123,8 +128,11 @@ module usb_cdc_channel
 | 
	
		
			
				|  |  |     wire [water_bits:0]	txused_msb = txused[fifo_bits-1:fifo_bits-water_bits];
 | 
	
		
			
				|  |  |     wire		        inport_empty_w;
 | 
	
		
			
				|  |  |     reg			inport_valid_q;
 | 
	
		
			
				|  |  | +   reg			flush_tx_data;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     cdc_fifo txfifo (
 | 
	
		
			
				|  |  | +		    .aclr    ( flush_tx_data ),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		    .wrclk   ( sys_clk ),
 | 
	
		
			
				|  |  |  		    .data    ( cpu_wdata[7:0] ),
 | 
	
		
			
				|  |  |  		    .wrreq   ( fifo_access & ~fifo_access_q & cpu_wstrb[0] ),
 | 
	
	
		
			
				|  | @@ -142,10 +150,13 @@ module usb_cdc_channel
 | 
	
		
			
				|  |  |  		    .rdusedw ( )
 | 
	
		
			
				|  |  |  		    );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +   // If RTS is not asserted, suspend data transmit
 | 
	
		
			
				|  |  | +   wire inport_has_data = ~inport_empty_w & inport_rts_w;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |     always @(posedge clk_i or posedge rst_i)
 | 
	
		
			
				|  |  |       if (rst_i)
 | 
	
		
			
				|  |  |         inport_valid_q <= 1'b0;
 | 
	
		
			
				|  |  | -     else if ( ~inport_empty_w )
 | 
	
		
			
				|  |  | +     else if ( inport_has_data )
 | 
	
		
			
				|  |  |         inport_valid_q <= 1'b1;
 | 
	
		
			
				|  |  |       else if ( data_ep.u.tx_data_accept )
 | 
	
		
			
				|  |  |         inport_valid_q <= 1'b0;
 | 
	
	
		
			
				|  | @@ -156,7 +167,7 @@ module usb_cdc_channel
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     // Must terminate a transfer at the max packet size
 | 
	
		
			
				|  |  |     reg [packet_bits-1:0] inport_cnt_q;
 | 
	
		
			
				|  |  | -   wire			 inport_last_w = inport_empty_w | &inport_cnt_q;
 | 
	
		
			
				|  |  | +   wire			 inport_last_w = ~inport_has_data | &inport_cnt_q;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     always @(posedge clk_i or posedge rst_i)
 | 
	
		
			
				|  |  |       if (rst_i)
 | 
	
	
		
			
				|  | @@ -171,15 +182,21 @@ module usb_cdc_channel
 | 
	
		
			
				|  |  |     wire [7:0]	        rdata_fifo;
 | 
	
		
			
				|  |  |     wire		        rxempty;
 | 
	
		
			
				|  |  |     wire		        rxfull;
 | 
	
		
			
				|  |  | +   reg			flush_rx_data;
 | 
	
		
			
				|  |  |     wire [fifo_bits-1:0] rxused;
 | 
	
		
			
				|  |  |     wire [water_bits:0]	rxused_msb = rxused[fifo_bits-1:fifo_bits-water_bits];
 | 
	
		
			
				|  |  |     wire [fifo_bits-1:0] outport_used_w;
 | 
	
		
			
				|  |  | +   wire			outport_full_w;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     wire			outport_valid_w = data_ep.u.rx_valid & data_ep.uc.rx_strb;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   assign data_ep.d.rx_space = outport_used_w <= fifo_size - packet_size;
 | 
	
		
			
				|  |  | +   // Should be space for a max-sized packet before allowing input
 | 
	
		
			
				|  |  | +   assign data_ep.d.rx_space = ~outport_full_w &
 | 
	
		
			
				|  |  | +			       (outport_used_w < fifo_size - packet_size);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     cdc_fifo rxfifo (
 | 
	
		
			
				|  |  | +		    .aclr    ( flush_rx_data ),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		    .rdclk   ( sys_clk ),
 | 
	
		
			
				|  |  |  		    .q       ( rdata_fifo ),
 | 
	
		
			
				|  |  |  		    .rdreq   ( fifo_access & ~fifo_access_q & ~|cpu_wstrb ),
 | 
	
	
		
			
				|  | @@ -191,7 +208,7 @@ module usb_cdc_channel
 | 
	
		
			
				|  |  |  		    .data    ( data_ep.uc.rx_data ),
 | 
	
		
			
				|  |  |  		    .wrreq   ( outport_valid_w ),
 | 
	
		
			
				|  |  |  		    .wrempty ( ),
 | 
	
		
			
				|  |  | -		    .wrfull  ( ),
 | 
	
		
			
				|  |  | +		    .wrfull  ( outport_full_w ),
 | 
	
		
			
				|  |  |  		    .wrusedw ( outport_used_w )
 | 
	
		
			
				|  |  |  		    );
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -223,7 +240,6 @@ module usb_cdc_channel
 | 
	
		
			
				|  |  |        .q     ( recv_break_s )
 | 
	
		
			
				|  |  |        );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   reg [1:0]   control_lines_q;
 | 
	
		
			
				|  |  |     wire [1:0]  control_lines_s;
 | 
	
		
			
				|  |  |     always @(posedge rst_i or posedge clk_i)
 | 
	
		
			
				|  |  |       if (rst_i)
 | 
	
	
		
			
				|  | @@ -244,15 +260,19 @@ module usb_cdc_channel
 | 
	
		
			
				|  |  |     always @(negedge rst_n or posedge sys_clk)
 | 
	
		
			
				|  |  |       if (~rst_n)
 | 
	
		
			
				|  |  |         begin
 | 
	
		
			
				|  |  | -	  water_ctl   <= 16'hc3c3 & water_ctl_mask;
 | 
	
		
			
				|  |  | -	  irq_mask     <= 16'b0;
 | 
	
		
			
				|  |  | -	  irq_pol      <= 16'b0;
 | 
	
		
			
				|  |  | -	  recv_break_q <= 1'b0;
 | 
	
		
			
				|  |  | +	  water_ctl     <= 16'hc3c3 & water_ctl_mask;
 | 
	
		
			
				|  |  | +	  irq_mask      <= 16'b0;
 | 
	
		
			
				|  |  | +	  irq_pol       <= 16'b0;
 | 
	
		
			
				|  |  | +	  recv_break_q  <= 1'b0;
 | 
	
		
			
				|  |  | +	  flush_rx_data <= 1'b0;
 | 
	
		
			
				|  |  | +	  flush_tx_data <= 1'b0;
 | 
	
		
			
				|  |  |         end
 | 
	
		
			
				|  |  |       else
 | 
	
		
			
				|  |  |         begin
 | 
	
		
			
				|  |  | -	  if (recv_break_s)
 | 
	
		
			
				|  |  | -	    recv_break_q <= 1'b1;
 | 
	
		
			
				|  |  | +	  flush_rx_data <= flush_rx_data & ~rxempty;
 | 
	
		
			
				|  |  | +	  flush_tx_data <= flush_tx_data & ~txempty;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	  recv_break_q  <= recv_break_q | recv_break_s;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	  if (cpu_valid)
 | 
	
		
			
				|  |  |  	    case (cpu_addr)
 | 
	
	
		
			
				|  | @@ -263,8 +283,13 @@ module usb_cdc_channel
 | 
	
		
			
				|  |  |  		     water_ctl[15:8] <= cpu_wdata[15:8] & water_ctl_mask[15:8];
 | 
	
		
			
				|  |  |  		end
 | 
	
		
			
				|  |  |  	      2'b10: begin
 | 
	
		
			
				|  |  | +		 if (cpu_wstrb[0] & cpu_wdata[0])
 | 
	
		
			
				|  |  | +		   flush_tx_data <= ~txempty;
 | 
	
		
			
				|  |  | +		 if (cpu_wstrb[0] & cpu_wdata[4])
 | 
	
		
			
				|  |  | +		   flush_rx_data <= ~rxempty;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		 if (cpu_wstrb[1] & cpu_wdata[9])
 | 
	
		
			
				|  |  | -		   recv_break_q <= 1'b0;
 | 
	
		
			
				|  |  | +		   recv_break_q <= recv_break_s;
 | 
	
		
			
				|  |  |  	      end
 | 
	
		
			
				|  |  |  	      2'b11: begin
 | 
	
		
			
				|  |  |  		 if (cpu_wstrb[0])
 |