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