|
@@ -57,7 +57,8 @@
|
|
|
// 9 - BREAK received (sticky, W1C)
|
|
|
// 10 - USB device configured
|
|
|
// 3 - RW - interrupt enable register
|
|
|
-// * - mask of corresponding status bits
|
|
|
+// 15:0 - mask of corresponding status bits
|
|
|
+// 31:16 - invert polarity (0 = irq on status 1, 1 = irq on status 0)
|
|
|
|
|
|
module usb_cdc_channel
|
|
|
#(parameter [3:0] data_ep_num = 4'd1,
|
|
@@ -67,10 +68,10 @@ module usb_cdc_channel
|
|
|
input rst_n,
|
|
|
input sys_clk,
|
|
|
input cpu_valid,
|
|
|
- input [1:0] cpu_addr,
|
|
|
+ input [1:0] cpu_addr,
|
|
|
output [31:0] cpu_rdata,
|
|
|
input [31:0] cpu_wdata,
|
|
|
- input cpu_wstrb,
|
|
|
+ input [3:0] cpu_wstrb,
|
|
|
output irq,
|
|
|
|
|
|
// Core FIFO interface
|
|
@@ -106,7 +107,7 @@ module usb_cdc_channel
|
|
|
always @(posedge sys_clk)
|
|
|
begin
|
|
|
fifo_access_q <= fifo_access;
|
|
|
- fifo_read_q <= fifo_access & ~cpu_wstrb;
|
|
|
+ fifo_read_q <= fifo_access & ~cpu_wstrb[0];
|
|
|
end
|
|
|
|
|
|
wire txempty;
|
|
@@ -119,7 +120,7 @@ module usb_cdc_channel
|
|
|
cdc_fifo txfifo (
|
|
|
.wrclk ( sys_clk ),
|
|
|
.data ( cpu_wdata[7:0] ),
|
|
|
- .wrreq ( fifo_access & ~fifo_access_q & cpu_wstrb ),
|
|
|
+ .wrreq ( fifo_access & ~fifo_access_q & cpu_wstrb[0] ),
|
|
|
.wrempty ( txempty ),
|
|
|
.wrfull ( txfull ),
|
|
|
.wrusedw ( txused ),
|
|
@@ -174,7 +175,7 @@ module usb_cdc_channel
|
|
|
cdc_fifo rxfifo (
|
|
|
.rdclk ( sys_clk ),
|
|
|
.q ( rdata_fifo ),
|
|
|
- .rdreq ( fifo_access & ~fifo_access_q & ~cpu_wstrb ),
|
|
|
+ .rdreq ( fifo_access & ~fifo_access_q & ~|cpu_wstrb ),
|
|
|
.rdempty ( rxempty ),
|
|
|
.rdfull ( rxfull ),
|
|
|
.rdusedw ( rxused ),
|
|
@@ -200,6 +201,7 @@ module usb_cdc_channel
|
|
|
|
|
|
wire [15:0] status_mask = 16'b0000_0111_1111_1111; // Implemented bit mask
|
|
|
reg [15:0] irq_mask;
|
|
|
+ reg [15:0] irq_pol;
|
|
|
wire [ 3:0] water_mask = 4'b1111 << (4-water_bits);
|
|
|
wire [15:0] water_ctl_mask = {4{water_mask}};
|
|
|
reg [15:0] water_ctl;
|
|
@@ -218,8 +220,9 @@ 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;
|
|
|
+ water_ctl <= 16'hc3c3 & water_ctl_mask;
|
|
|
+irq_mask <= 16'b0;
|
|
|
+ irq_pol <= 16'b0;
|
|
|
recv_break_q <= 1'b0;
|
|
|
end
|
|
|
else
|
|
@@ -227,12 +230,31 @@ module usb_cdc_channel
|
|
|
if (recv_break_s)
|
|
|
recv_break_q <= 1'b1;
|
|
|
|
|
|
- if (cpu_valid & cpu_wstrb)
|
|
|
+ if (cpu_valid)
|
|
|
case (cpu_addr)
|
|
|
- 2'b01: water_ctl <= cpu_wdata[15:0] & water_ctl_mask;
|
|
|
- 2'b10: if (cpu_wdata[9]) recv_break_q <= 1'b0;
|
|
|
- 2'b11: irq_mask <= cpu_wdata[15:0] & status_mask;
|
|
|
- default: /* do nothing */;
|
|
|
+ 2'b01: begin
|
|
|
+ if (cpu_wstrb[0])
|
|
|
+ water_ctl[7:0] <= cpu_wdata[7:0] & water_ctl_mask[7:0];
|
|
|
+ if (cpu_wstrb[1])
|
|
|
+ water_ctl[15:8] <= cpu_wdata[15:8] & water_ctl_mask[15:8];
|
|
|
+ end
|
|
|
+ 2'b10: begin
|
|
|
+ if (cpu_wstrb[1] & cpu_wdata[9])
|
|
|
+ recv_break_q <= 1'b0;
|
|
|
+ end
|
|
|
+ 2'b11: begin
|
|
|
+ if (cpu_wstrb[0])
|
|
|
+ irq_mask[7:0] <= cpu_wdata[7:0] & status_mask[7:0];
|
|
|
+ if (cpu_wstrb[1])
|
|
|
+ irq_mask[15:8] <= cpu_wdata[15:8] & status_mask[15:8];
|
|
|
+ if (cpu_wstrb[2])
|
|
|
+ irq_pol[7:0] <= cpu_wdata[23:16] & status_mask[7:0];
|
|
|
+ if (cpu_wstrb[3])
|
|
|
+ irq_pol[15:8] <= cpu_wdata[31:24] & status_mask[15:8];
|
|
|
+ end
|
|
|
+ default: begin
|
|
|
+ /* do nothing */
|
|
|
+ end
|
|
|
endcase // case (cpu_addr)
|
|
|
end // else: !if(~rst_n)
|
|
|
|
|
@@ -253,14 +275,14 @@ module usb_cdc_channel
|
|
|
assign status[9] = recv_break_q;
|
|
|
assign status[10] = usb_configured;
|
|
|
|
|
|
- assign irq = |(status & irq_mask);
|
|
|
+ assign irq = |((status ^ irq_pol) & irq_mask);
|
|
|
|
|
|
always @(*)
|
|
|
case (cpu_addr)
|
|
|
2'b00: cpu_rdata = { 24'b0, rdata_fifo };
|
|
|
2'b01: cpu_rdata = { 16'b0, water_ctl };
|
|
|
2'b10: cpu_rdata = { 16'b0, status };
|
|
|
- 2'b11: cpu_rdata = { 16'b0, irq_mask };
|
|
|
+ 2'b11: cpu_rdata = { irq_pol, irq_mask };
|
|
|
default: cpu_rdata = 32'bx;
|
|
|
endcase // case (cpu_addr)
|
|
|
|