|
@@ -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])
|