|  | @@ -34,42 +34,303 @@
 | 
	
		
			
				|  |  |  // Boston, MA  02111-1307  USA
 | 
	
		
			
				|  |  |  //-----------------------------------------------------------------
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -module usb_cdc_core
 | 
	
		
			
				|  |  | +// Multiport CDC interface
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// Each channel contains the following registers seen from the CPU:
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// 0 - RW - FIFO read/write data register
 | 
	
		
			
				|  |  | +// 1 - RW - watermark control
 | 
	
		
			
				|  |  | +//         3:1 - transmit FIFO low watermark  (resets to 1/4)
 | 
	
		
			
				|  |  | +//         7:5 - transmit FIFO high watermark (resets to 3/4)
 | 
	
		
			
				|  |  | +//        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
 | 
	
		
			
				|  |  | +//           1 - transmit FIFO <= low watermark
 | 
	
		
			
				|  |  | +//           2 - transmit FIFO >= high watermark
 | 
	
		
			
				|  |  | +//           3 - transmit FIFO full
 | 
	
		
			
				|  |  | +//           4 - receive FIFO empty
 | 
	
		
			
				|  |  | +//           5 - receive FIFO <= low watermark
 | 
	
		
			
				|  |  | +//           6 - receive FIFO >= high watermark
 | 
	
		
			
				|  |  | +//           7 - receive FIFO full
 | 
	
		
			
				|  |  | +//           8 - receive FIFO not empty after two USB frames
 | 
	
		
			
				|  |  | +//           9 - BREAK received (sticky, W1C)
 | 
	
		
			
				|  |  | +//          10 - USB device configured
 | 
	
		
			
				|  |  | +// 3 - RW - interrupt enable register
 | 
	
		
			
				|  |  | +//           * - mask of corresponding status bits
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +module usb_cdc_channel
 | 
	
		
			
				|  |  | +  #(parameter [3:0] data_ep_num = 4'd1,
 | 
	
		
			
				|  |  | +    parameter [3:0] intr_ep_num = data_ep_num+1'b1)
 | 
	
		
			
				|  |  |    (
 | 
	
		
			
				|  |  | -   // Inputs
 | 
	
		
			
				|  |  | -   input	 clk_i
 | 
	
		
			
				|  |  | -		 ,input rst_i
 | 
	
		
			
				|  |  | -		 ,input enable_i
 | 
	
		
			
				|  |  | -		 ,input [ 7:0] utmi_data_in_i
 | 
	
		
			
				|  |  | -		 ,input utmi_txready_i
 | 
	
		
			
				|  |  | -		 ,input utmi_rxvalid_i
 | 
	
		
			
				|  |  | -		 ,input utmi_rxactive_i
 | 
	
		
			
				|  |  | -		 ,input utmi_rxerror_i
 | 
	
		
			
				|  |  | -		 ,input [ 1:0] utmi_linestate_i
 | 
	
		
			
				|  |  | -		 ,input inport_valid_i
 | 
	
		
			
				|  |  | -		 ,input [ 7:0] inport_data_i
 | 
	
		
			
				|  |  | -		 ,input outport_accept_i
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 // Outputs
 | 
	
		
			
				|  |  | -		 ,output [ 7:0] utmi_data_out_o
 | 
	
		
			
				|  |  | -		 ,output utmi_txvalid_o
 | 
	
		
			
				|  |  | -		 ,output [ 1:0] utmi_op_mode_o
 | 
	
		
			
				|  |  | -		 ,output [ 1:0] utmi_xcvrselect_o
 | 
	
		
			
				|  |  | -		 ,output utmi_termselect_o
 | 
	
		
			
				|  |  | -		 ,output utmi_dppulldown_o
 | 
	
		
			
				|  |  | -		 ,output utmi_dmpulldown_o
 | 
	
		
			
				|  |  | -		 ,output inport_accept_o
 | 
	
		
			
				|  |  | -		 ,output outport_valid_o
 | 
	
		
			
				|  |  | -		 ,output [ 7:0] outport_data_o
 | 
	
		
			
				|  |  | -		 ,output outport_break_o,
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |     // CPU bus
 | 
	
		
			
				|  |  | +   input	 rst_n,
 | 
	
		
			
				|  |  |     input	 sys_clk,
 | 
	
		
			
				|  |  |     input	 cpu_valid,
 | 
	
		
			
				|  |  | -   input [15:0]  cpu_addr,
 | 
	
		
			
				|  |  | +   input [1:0]	 cpu_addr,
 | 
	
		
			
				|  |  |     output [31:0] cpu_rdata,
 | 
	
		
			
				|  |  |     input [31:0]  cpu_wdata,
 | 
	
		
			
				|  |  | -   input [3:0]	 cpu_wstrb
 | 
	
		
			
				|  |  | +   input	 cpu_wstrb,
 | 
	
		
			
				|  |  | +   output	 irq,
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // Core FIFO interface
 | 
	
		
			
				|  |  | +   input	 clk_i,
 | 
	
		
			
				|  |  | +   input	 rst_i,
 | 
	
		
			
				|  |  | +		 usb_endpoint.dstr data_ep,
 | 
	
		
			
				|  |  | +		 usb_endpoint.dstr intr_ep,
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // Control signals
 | 
	
		
			
				|  |  | +   input	 recv_break_i,
 | 
	
		
			
				|  |  | +   output	 recv_break_o, // sys_clk domain, reflects the status register
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // USB status
 | 
	
		
			
				|  |  | +   input	 usb_configured,
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // Top of frame strobe *in sys_clk domain*
 | 
	
		
			
				|  |  | +   input	 start_of_frame_s
 | 
	
		
			
				|  |  | +   );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   localparam fifo_size   = 511;
 | 
	
		
			
				|  |  | +   localparam fifo_bits   = $clog2(fifo_size);
 | 
	
		
			
				|  |  | +   localparam packet_bits = 6;
 | 
	
		
			
				|  |  | +   localparam packet_size = 1 << packet_bits;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // Up to four bits per watermark, but all are not necessarily
 | 
	
		
			
				|  |  | +   // implemented
 | 
	
		
			
				|  |  | +   localparam water_bits  = 3;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   wire		 fifo_access = cpu_valid & cpu_addr == 2'b00;
 | 
	
		
			
				|  |  | +   reg		 fifo_access_q;
 | 
	
		
			
				|  |  | +   reg		 fifo_read_q;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   always @(posedge sys_clk)
 | 
	
		
			
				|  |  | +     begin
 | 
	
		
			
				|  |  | +	fifo_access_q <= fifo_access;
 | 
	
		
			
				|  |  | +	fifo_read_q   <= fifo_access & ~cpu_wstrb;
 | 
	
		
			
				|  |  | +     end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   wire		        txempty;
 | 
	
		
			
				|  |  | +   wire		        txfull;
 | 
	
		
			
				|  |  | +   wire [fifo_bits-1:0] txused;
 | 
	
		
			
				|  |  | +   wire [water_bits:0]	txused_msb = txused[fifo_bits-1:fifo_bits-water_bits];
 | 
	
		
			
				|  |  | +   wire		        inport_empty_w;
 | 
	
		
			
				|  |  | +   reg			inport_valid_q;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   cdc_fifo txfifo (
 | 
	
		
			
				|  |  | +		    .wrclk   ( sys_clk ),
 | 
	
		
			
				|  |  | +		    .data    ( cpu_wdata[7:0] ),
 | 
	
		
			
				|  |  | +		    .wrreq   ( fifo_access & ~fifo_access_q & cpu_wstrb ),
 | 
	
		
			
				|  |  | +		    .wrempty ( txempty ),
 | 
	
		
			
				|  |  | +		    .wrfull  ( txfull ),
 | 
	
		
			
				|  |  | +		    .wrusedw ( txused ),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		    .rdclk   ( clk_i ),
 | 
	
		
			
				|  |  | +		    .q       ( data_ep.d.tx_data ),
 | 
	
		
			
				|  |  | +		    .rdreq   ( ~inport_valid_q | data_ep.u.tx_data_accept ),
 | 
	
		
			
				|  |  | +		    .rdempty ( inport_empty_w ),
 | 
	
		
			
				|  |  | +		    .rdfull  ( ),
 | 
	
		
			
				|  |  | +		    .rdusedw ( )
 | 
	
		
			
				|  |  | +		    );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   always @(posedge clk_i or posedge rst_i)
 | 
	
		
			
				|  |  | +     if (rst_i)
 | 
	
		
			
				|  |  | +       inport_valid_q <= 1'b0;
 | 
	
		
			
				|  |  | +     else if ( ~inport_empty_w )
 | 
	
		
			
				|  |  | +       inport_valid_q <= 1'b1;
 | 
	
		
			
				|  |  | +     else if ( data_ep.u.tx_data_accept )
 | 
	
		
			
				|  |  | +       inport_valid_q <= 1'b0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   assign data_ep.d.tx_data_valid = inport_valid_q;
 | 
	
		
			
				|  |  | +   assign data_ep.d.tx_ready      = inport_valid_q;
 | 
	
		
			
				|  |  | +   assign data_ep.d.tx_data_strb  = inport_valid_q;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // 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;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   always @(posedge clk_i or posedge rst_i)
 | 
	
		
			
				|  |  | +     if (rst_i)
 | 
	
		
			
				|  |  | +       inport_cnt_q <= 'd0;
 | 
	
		
			
				|  |  | +     else if (inport_last_w & data_ep.u.tx_data_accept)
 | 
	
		
			
				|  |  | +       inport_cnt_q <= 'd0;
 | 
	
		
			
				|  |  | +     else if (inport_valid_q & data_ep.u.tx_data_accept)
 | 
	
		
			
				|  |  | +       inport_cnt_q <= inport_cnt_q + 1'b1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   assign data_ep.d.tx_data_last = inport_last_w;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   wire [7:0]	        rdata_fifo;
 | 
	
		
			
				|  |  | +   wire		        rxempty;
 | 
	
		
			
				|  |  | +   wire		        rxfull;
 | 
	
		
			
				|  |  | +   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_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;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   cdc_fifo rxfifo (
 | 
	
		
			
				|  |  | +		    .rdclk   ( sys_clk ),
 | 
	
		
			
				|  |  | +		    .q       ( rdata_fifo ),
 | 
	
		
			
				|  |  | +		    .rdreq   ( fifo_access & ~fifo_access_q & ~cpu_wstrb ),
 | 
	
		
			
				|  |  | +		    .rdempty ( rxempty ),
 | 
	
		
			
				|  |  | +		    .rdfull  ( rxfull ),
 | 
	
		
			
				|  |  | +		    .rdusedw ( rxused ),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		    .wrclk   ( clk_i ),
 | 
	
		
			
				|  |  | +		    .data    ( data_ep.uc.rx_data ),
 | 
	
		
			
				|  |  | +		    .wrreq   ( outport_valid_w ),
 | 
	
		
			
				|  |  | +		    .wrempty ( ),
 | 
	
		
			
				|  |  | +		    .wrfull  ( ),
 | 
	
		
			
				|  |  | +		    .wrusedw ( outport_used_w )
 | 
	
		
			
				|  |  | +		    );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // Queued data wakeup
 | 
	
		
			
				|  |  | +   reg [1:0]		had_rxdata;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   always @(posedge sys_clk)
 | 
	
		
			
				|  |  | +     begin
 | 
	
		
			
				|  |  | +	if (start_of_frame_s)
 | 
	
		
			
				|  |  | +	  had_rxdata <= { had_rxdata[0], 1'b1 };
 | 
	
		
			
				|  |  | +	if (rxempty)
 | 
	
		
			
				|  |  | +	  had_rxdata <= 2'b00;
 | 
	
		
			
				|  |  | +     end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   wire [15:0] status_mask = 16'b0000_0111_1111_1111; // Implemented bit mask
 | 
	
		
			
				|  |  | +   reg  [15:0] irq_mask;
 | 
	
		
			
				|  |  | +   wire [ 3:0] water_mask     = 4'b1111 << (4-water_bits);
 | 
	
		
			
				|  |  | +   wire [15:0] water_ctl_mask = {4{water_mask}};
 | 
	
		
			
				|  |  | +   reg  [15:0] water_ctl;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   wire        recv_break_s;
 | 
	
		
			
				|  |  | +   reg	       recv_break_q;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   synchronizer #(.width(1)) break_synchro
 | 
	
		
			
				|  |  | +     (
 | 
	
		
			
				|  |  | +      .rst_n ( rst_n ),
 | 
	
		
			
				|  |  | +      .clk   ( sys_clk ),
 | 
	
		
			
				|  |  | +      .d     ( recv_break_i ),
 | 
	
		
			
				|  |  | +      .q     ( recv_break_s )
 | 
	
		
			
				|  |  | +      );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   always @(negedge rst_n or posedge sys_clk)
 | 
	
		
			
				|  |  | +     if (~rst_n)
 | 
	
		
			
				|  |  | +       begin
 | 
	
		
			
				|  |  | +	  water_ctl    <= 16'h8787 & water_ctl_mask;
 | 
	
		
			
				|  |  | +	  irq_mask     <= 16'b0;
 | 
	
		
			
				|  |  | +	  recv_break_q <= 1'b0;
 | 
	
		
			
				|  |  | +       end
 | 
	
		
			
				|  |  | +     else
 | 
	
		
			
				|  |  | +       begin
 | 
	
		
			
				|  |  | +	  if (recv_break_s)
 | 
	
		
			
				|  |  | +	    recv_break_q <= 1'b1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	  if (cpu_valid & cpu_wstrb)
 | 
	
		
			
				|  |  | +	    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 */;
 | 
	
		
			
				|  |  | +	    endcase // case (cpu_addr)
 | 
	
		
			
				|  |  | +       end // else: !if(~rst_n)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   assign recv_break_o = recv_break_q; // Available to external logic
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   tri0 [15:0] status;
 | 
	
		
			
				|  |  | +   assign status[0]    = txempty;
 | 
	
		
			
				|  |  | +   assign status[1]    = (txused_msb <= water_ctl[3:4-water_bits]);
 | 
	
		
			
				|  |  | +   assign status[2]    = (txused_msb >= water_ctl[7:8-water_bits]);
 | 
	
		
			
				|  |  | +   assign status[3]    = txfull;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   assign status[4]    = rxempty;
 | 
	
		
			
				|  |  | +   assign status[5]    = (rxused_msb <= water_ctl[11:12-water_bits]);
 | 
	
		
			
				|  |  | +   assign status[6]    = (rxused_msb >= water_ctl[15:16-water_bits]);
 | 
	
		
			
				|  |  | +   assign status[7]    = rxfull;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   assign status[8]    = had_rxdata[1];
 | 
	
		
			
				|  |  | +   assign status[9]    = recv_break_q;
 | 
	
		
			
				|  |  | +   assign status[10]   = usb_configured;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   assign irq = |(status & 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 };
 | 
	
		
			
				|  |  | +       default: cpu_rdata = 32'bx;
 | 
	
		
			
				|  |  | +     endcase // case (cpu_addr)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // Channel configurations
 | 
	
		
			
				|  |  | +   assign data_ep.c.ep_num  = data_ep_num;
 | 
	
		
			
				|  |  | +   assign data_ep.c.ep_mask = 4'b1111;
 | 
	
		
			
				|  |  | +   assign intr_ep.c.ep_num  = intr_ep_num;
 | 
	
		
			
				|  |  | +   assign intr_ep.c.ep_mask = 4'b1111;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // Data channel endpoint: unused signals
 | 
	
		
			
				|  |  | +   assign data_ep.d.ep_iso        = 1'b0;
 | 
	
		
			
				|  |  | +   assign data_ep.d.cfg_int_rx    = 1'b0;
 | 
	
		
			
				|  |  | +   assign data_ep.d.cfg_int_tx    = 1'b0;
 | 
	
		
			
				|  |  | +   assign data_ep.d.ep_stall      = 1'b0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // Notification channel endpoint: currently never used at all
 | 
	
		
			
				|  |  | +   assign intr_ep.d.ep_iso        = 1'b0;
 | 
	
		
			
				|  |  | +   assign intr_ep.d.cfg_int_rx    = 1'b0;
 | 
	
		
			
				|  |  | +   assign intr_ep.d.cfg_int_tx    = 1'b0;
 | 
	
		
			
				|  |  | +   assign intr_ep.d.ep_stall      = 1'b0;
 | 
	
		
			
				|  |  | +   assign intr_ep.d.tx_ready      = 1'b0;
 | 
	
		
			
				|  |  | +   assign intr_ep.d.tx_data_valid = 1'b0;
 | 
	
		
			
				|  |  | +   assign intr_ep.d.tx_data_strb  = 1'b0;
 | 
	
		
			
				|  |  | +   assign intr_ep.d.tx_data       = 8'bx;
 | 
	
		
			
				|  |  | +   assign intr_ep.d.tx_data_last  = 1'b0;
 | 
	
		
			
				|  |  | +   assign intr_ep.d.rx_space      = 1'b0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +endmodule // usb_cdc_channel
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +module usb_cdc_core
 | 
	
		
			
				|  |  | +  #( parameter [2:0] channels = 3'd1 )
 | 
	
		
			
				|  |  | +  (
 | 
	
		
			
				|  |  | +   // Inputs
 | 
	
		
			
				|  |  | +   input		 clk_i,
 | 
	
		
			
				|  |  | +   input		 rst_i,
 | 
	
		
			
				|  |  | +   input		 enable_i,
 | 
	
		
			
				|  |  | +   input [ 7:0]		 utmi_data_in_i,
 | 
	
		
			
				|  |  | +   input		 utmi_txready_i,
 | 
	
		
			
				|  |  | +   input		 utmi_rxvalid_i,
 | 
	
		
			
				|  |  | +   input		 utmi_rxactive_i,
 | 
	
		
			
				|  |  | +   input		 utmi_rxerror_i,
 | 
	
		
			
				|  |  | +   input [ 1:0]		 utmi_linestate_i,
 | 
	
		
			
				|  |  | +   //input		 inport_valid_i,
 | 
	
		
			
				|  |  | +   //input [ 7:0]	 inport_data_i,
 | 
	
		
			
				|  |  | +   //input		 outport_accept_i,
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // Outputs
 | 
	
		
			
				|  |  | +   output [ 7:0]	 utmi_data_out_o,
 | 
	
		
			
				|  |  | +   output		 utmi_txvalid_o,
 | 
	
		
			
				|  |  | +   output [ 1:0]	 utmi_op_mode_o,
 | 
	
		
			
				|  |  | +   output [ 1:0]	 utmi_xcvrselect_o,
 | 
	
		
			
				|  |  | +   output		 utmi_termselect_o,
 | 
	
		
			
				|  |  | +   output		 utmi_dppulldown_o,
 | 
	
		
			
				|  |  | +   output		 utmi_dmpulldown_o,
 | 
	
		
			
				|  |  | +   output [channels-1:0] recv_break_o,
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   //output		 inport_accept_o,
 | 
	
		
			
				|  |  | +   //output		 outport_valid_o,
 | 
	
		
			
				|  |  | +   //output [ 7:0]	 outport_data_o,
 | 
	
		
			
				|  |  | +   //output		 outport_break_o,
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // CPU bus
 | 
	
		
			
				|  |  | +   input		 rst_n,
 | 
	
		
			
				|  |  | +   input		 sys_clk,
 | 
	
		
			
				|  |  | +   input		 cpu_valid_cdc,
 | 
	
		
			
				|  |  | +   input		 cpu_valid_usbdesc,
 | 
	
		
			
				|  |  | +   input  [31:0]	 cpu_addr,
 | 
	
		
			
				|  |  | +   output [31:0]	 cpu_rdata_cdc,
 | 
	
		
			
				|  |  | +   output [31:0]	 cpu_rdata_usbdesc,
 | 
	
		
			
				|  |  | +   input  [31:0]	 cpu_wdata,
 | 
	
		
			
				|  |  | +   input   [3:0]	 cpu_wstrb,
 | 
	
		
			
				|  |  | +   output [channels-1:0] irq
 | 
	
		
			
				|  |  |     );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     parameter USB_SPEED_HS = "False"; // True or False
 | 
	
	
		
			
				|  | @@ -168,7 +429,7 @@ module usb_cdc_core
 | 
	
		
			
				|  |  |     wire  usb_reset_w;
 | 
	
		
			
				|  |  |     reg [6:0] device_addr_q;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   localparam endpoint_channels = 4;
 | 
	
		
			
				|  |  | +   localparam endpoint_channels = channels*2 + 1;
 | 
	
		
			
				|  |  |     usb_endpoint usb_ep [0:endpoint_channels-1] ();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     wire       utmi_chirp_en_w;
 | 
	
	
		
			
				|  | @@ -391,13 +652,15 @@ module usb_cdc_core
 | 
	
		
			
				|  |  |     //-----------------------------------------------------------------
 | 
	
		
			
				|  |  |     // Core
 | 
	
		
			
				|  |  |     //-----------------------------------------------------------------
 | 
	
		
			
				|  |  | +   wire start_of_frame_w;		// Or reset, but close enough
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |     usbf_device_core #(.endpoint_channels(endpoint_channels))
 | 
	
		
			
				|  |  |       u_core
 | 
	
		
			
				|  |  |         (
 | 
	
		
			
				|  |  |  	.clk_i(clk_i),
 | 
	
		
			
				|  |  |  	.rst_i(rst_i),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	.intr_o(),
 | 
	
		
			
				|  |  | +	.intr_o(start_of_frame_w),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// UTMI interface
 | 
	
		
			
				|  |  |  	.utmi_data_o(utmi_data_out_o),
 | 
	
	
		
			
				|  | @@ -519,8 +782,7 @@ module usb_cdc_core
 | 
	
		
			
				|  |  |     reg [15:0]  desc_base_addr_r;
 | 
	
		
			
				|  |  |     reg [15:0]  desc_len_r;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   reg	       rx_break_q;
 | 
	
		
			
				|  |  | -   reg	       rx_break_r;
 | 
	
		
			
				|  |  | +   reg [7:0]   rx_break_r;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     reg	       addressed_q;
 | 
	
		
			
				|  |  |     reg	       addressed_r;
 | 
	
	
		
			
				|  | @@ -546,13 +808,14 @@ module usb_cdc_core
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     always @ *
 | 
	
		
			
				|  |  |       begin
 | 
	
		
			
				|  |  | -	ctrl_stall_r    = 1'b0;
 | 
	
		
			
				|  |  | -	ctrl_ack_r      = 1'b0;
 | 
	
		
			
				|  |  | -	device_addr_r   = device_addr_q;
 | 
	
		
			
				|  |  | -	addressed_r     = addressed_q;
 | 
	
		
			
				|  |  | -	configured_r    = configured_q;
 | 
	
		
			
				|  |  | -	set_with_data_r = set_with_data_q;
 | 
	
		
			
				|  |  | -	rx_break_r      = 1'b0;
 | 
	
		
			
				|  |  | +	ctrl_stall_r     = 1'b0;
 | 
	
		
			
				|  |  | +	ctrl_ack_r       = 1'b0;
 | 
	
		
			
				|  |  | +	ctrl_send_data_r = 1'b0;
 | 
	
		
			
				|  |  | +	device_addr_r    = device_addr_q;
 | 
	
		
			
				|  |  | +	addressed_r      = addressed_q;
 | 
	
		
			
				|  |  | +	configured_r     = configured_q;
 | 
	
		
			
				|  |  | +	set_with_data_r  = set_with_data_q;
 | 
	
		
			
				|  |  | +	rx_break_r       = 8'b0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if (setup_valid_q)
 | 
	
		
			
				|  |  |  	  begin
 | 
	
	
		
			
				|  | @@ -596,15 +859,10 @@ module usb_cdc_core
 | 
	
		
			
				|  |  |  			begin
 | 
	
		
			
				|  |  |  			   $display("SET_CONF: Configuration %x", wValue_w);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			   if (wValue_w == 16'd0)
 | 
	
		
			
				|  |  | -			     begin
 | 
	
		
			
				|  |  | -				configured_r = 1'b0;
 | 
	
		
			
				|  |  | -				ctrl_ack_r   = setup_set_w && setup_no_data_w;
 | 
	
		
			
				|  |  | -			     end
 | 
	
		
			
				|  |  |  			   // Only support one configuration for now
 | 
	
		
			
				|  |  | -			   else if (wValue_w == 16'd1)
 | 
	
		
			
				|  |  | +			   if (wValue_w < 16'd2)
 | 
	
		
			
				|  |  |  			     begin
 | 
	
		
			
				|  |  | -				configured_r = 1'b1;
 | 
	
		
			
				|  |  | +				configured_r = wValue_w[0];
 | 
	
		
			
				|  |  |  				ctrl_ack_r   = setup_set_w && setup_no_data_w;
 | 
	
		
			
				|  |  |  			     end
 | 
	
		
			
				|  |  |  			   else
 | 
	
	
		
			
				|  | @@ -615,14 +873,16 @@ module usb_cdc_core
 | 
	
		
			
				|  |  |  			   $display("GET_INTERFACE");
 | 
	
		
			
				|  |  |  			   ctrl_stall_r = 1'b1;
 | 
	
		
			
				|  |  |  			end
 | 
	
		
			
				|  |  | +//`ifdef HANDLE_SET_INTERFACE
 | 
	
		
			
				|  |  |  		      `REQ_SET_INTERFACE:
 | 
	
		
			
				|  |  |  			begin
 | 
	
		
			
				|  |  |  			   $display("SET_INTERFACE: %x %x", wValue_w, wIndex_w);
 | 
	
		
			
				|  |  | -			   if (wValue_w == 16'd0 && wIndex_w == 16'd0)
 | 
	
		
			
				|  |  | +			   if (wValue_w == 16'd0 && wIndex_w < (channels << 1))
 | 
	
		
			
				|  |  |  			     ctrl_ack_r   = setup_set_w && setup_no_data_w;
 | 
	
		
			
				|  |  |  			   else
 | 
	
		
			
				|  |  |  			     ctrl_stall_r = 1'b1;
 | 
	
		
			
				|  |  |  			end
 | 
	
		
			
				|  |  | +//`endif
 | 
	
		
			
				|  |  |  		      default:
 | 
	
		
			
				|  |  |  			begin
 | 
	
		
			
				|  |  |  			   ctrl_stall_r = 1'b1;
 | 
	
	
		
			
				|  | @@ -647,7 +907,7 @@ module usb_cdc_core
 | 
	
		
			
				|  |  |  			end
 | 
	
		
			
				|  |  |  		      `CDC_SEND_BREAK:
 | 
	
		
			
				|  |  |  			begin
 | 
	
		
			
				|  |  | -			   rx_break_r    = (wValue_w != 16'd0);
 | 
	
		
			
				|  |  | +			   rx_break_r[wIndex_w[3:1]] = wIndex_w[0] & |wValue_w;
 | 
	
		
			
				|  |  |  			end
 | 
	
		
			
				|  |  |  		      default:
 | 
	
		
			
				|  |  |  			begin
 | 
	
	
		
			
				|  | @@ -672,7 +932,6 @@ module usb_cdc_core
 | 
	
		
			
				|  |  |  	  addressed_q     <= 1'b0;
 | 
	
		
			
				|  |  |  	  configured_q    <= 1'b0;
 | 
	
		
			
				|  |  |  	  set_with_data_q <= 1'b0;
 | 
	
		
			
				|  |  | -	  rx_break_q      <= 1'b0;
 | 
	
		
			
				|  |  |         end
 | 
	
		
			
				|  |  |       else if (usb_reset_w)
 | 
	
		
			
				|  |  |         begin
 | 
	
	
		
			
				|  | @@ -680,7 +939,6 @@ module usb_cdc_core
 | 
	
		
			
				|  |  |  	  addressed_q     <= 1'b0;
 | 
	
		
			
				|  |  |  	  configured_q    <= 1'b0;
 | 
	
		
			
				|  |  |  	  set_with_data_q <= 1'b0;
 | 
	
		
			
				|  |  | -	  rx_break_q      <= 1'b0;
 | 
	
		
			
				|  |  |         end
 | 
	
		
			
				|  |  |       else
 | 
	
		
			
				|  |  |         begin
 | 
	
	
		
			
				|  | @@ -688,7 +946,6 @@ module usb_cdc_core
 | 
	
		
			
				|  |  |  	  addressed_q     <= addressed_r;
 | 
	
		
			
				|  |  |  	  configured_q    <= configured_r;
 | 
	
		
			
				|  |  |  	  set_with_data_q <= set_with_data_r;
 | 
	
		
			
				|  |  | -	  rx_break_q      <= rx_break_r;
 | 
	
		
			
				|  |  |         end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     //-----------------------------------------------------------------
 | 
	
	
		
			
				|  | @@ -874,126 +1131,85 @@ module usb_cdc_core
 | 
	
		
			
				|  |  |     assign usb_ep[0].d.tx_data_last  = ctrl_txlast_q;
 | 
	
		
			
				|  |  |     assign usb_ep[0].d.ep_stall      = ctrl_txstall_q;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +   // Unused endpoint 0 signals
 | 
	
		
			
				|  |  | +   assign usb_ep[0].d.ep_iso        = 1'b0;
 | 
	
		
			
				|  |  | +   assign usb_ep[0].d.cfg_int_rx    = 1'b0;
 | 
	
		
			
				|  |  | +   assign usb_ep[0].d.cfg_int_tx    = 1'b0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |     //-----------------------------------------------------------------
 | 
	
		
			
				|  |  |     // Descriptor ROM
 | 
	
		
			
				|  |  |     //-----------------------------------------------------------------
 | 
	
		
			
				|  |  | +   wire [7:0] rdata_usbdesc;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |     usb_desc_rom
 | 
	
		
			
				|  |  |       u_rom
 | 
	
		
			
				|  |  |         (
 | 
	
		
			
				|  |  | -	.clk		(clk_i),
 | 
	
		
			
				|  |  | -	.usb_addr	(desc_addr_r),
 | 
	
		
			
				|  |  | -	.usb_rdata	(desc_data_w),
 | 
	
		
			
				|  |  | +	.clk		( clk_i ),
 | 
	
		
			
				|  |  | +	.usb_addr	( desc_addr_r ),
 | 
	
		
			
				|  |  | +	.usb_rdata	( desc_data_w ),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// CPU interface for modifications
 | 
	
		
			
				|  |  | -	.cpu_clk        (sys_clk),
 | 
	
		
			
				|  |  | -	.cpu_addr	(cpu_addr),
 | 
	
		
			
				|  |  | -	.cpu_rdata	(cpu_rdata[7:0]),
 | 
	
		
			
				|  |  | -	.cpu_wdata	(cpu_wdata[7:0]),
 | 
	
		
			
				|  |  | -	.cpu_wren	(cpu_valid & cpu_wstrb[0])
 | 
	
		
			
				|  |  | +	.cpu_clk        ( sys_clk ),
 | 
	
		
			
				|  |  | +	.cpu_addr	( cpu_addr[17:2] ),
 | 
	
		
			
				|  |  | +	.cpu_rdata	( cpu_rdata_usbdesc[7:0] ),
 | 
	
		
			
				|  |  | +	.cpu_wdata	( cpu_wdata[7:0] ),
 | 
	
		
			
				|  |  | +	.cpu_wren	( cpu_valid_usbdesc & cpu_wstrb[0] )
 | 
	
		
			
				|  |  |  	);
 | 
	
		
			
				|  |  | -   assign cpu_rdata[31:8] = 24'bx;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   //-----------------------------------------------------------------
 | 
	
		
			
				|  |  | -   // Unused Endpoint Downstream Signals
 | 
	
		
			
				|  |  | -   //-----------------------------------------------------------------
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   assign usb_ep[0].d.ep_iso        = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[0].d.cfg_int_rx    = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[0].d.cfg_int_tx    = 1'b0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   // EP1: unused
 | 
	
		
			
				|  |  | -   assign usb_ep[1].d.ep_iso        = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[1].d.cfg_int_rx    = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[1].d.cfg_int_tx    = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[1].d.ep_stall      = 1'b1;
 | 
	
		
			
				|  |  | -   assign usb_ep[1].d.tx_ready      = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[1].d.tx_data_valid = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[1].d.tx_data_strb  = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[1].d.tx_data       = 8'bx;
 | 
	
		
			
				|  |  | -   assign usb_ep[1].d.tx_data_last  = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[1].d.rx_space      = 1'b0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   // EP2: data channel
 | 
	
		
			
				|  |  | -   assign usb_ep[2].d.ep_iso        = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[2].d.cfg_int_rx    = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[2].d.cfg_int_tx    = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[2].d.ep_stall      = 1'b0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   // EP3: notification output
 | 
	
		
			
				|  |  | -   assign usb_ep[3].d.ep_iso        = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[3].d.cfg_int_rx    = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[3].d.cfg_int_tx    = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[3].d.ep_stall      = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[3].d.tx_ready      = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[3].d.tx_data_valid = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[3].d.tx_data_strb  = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[3].d.tx_data       = 8'bx;
 | 
	
		
			
				|  |  | -   assign usb_ep[3].d.tx_data_last  = 1'b0;
 | 
	
		
			
				|  |  | -   assign usb_ep[3].d.rx_space      = 1'b0;
 | 
	
		
			
				|  |  | +   assign cpu_rdata_usbdesc[31:8] = 24'b0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     //-----------------------------------------------------------------
 | 
	
		
			
				|  |  | -   // Stream endpoint channel configuration
 | 
	
		
			
				|  |  | +   // Channel streaming interfaces and CPU interfaces
 | 
	
		
			
				|  |  |     //-----------------------------------------------------------------
 | 
	
		
			
				|  |  | -   assign usb_ep[1].c.ep_num        = 4'd1;
 | 
	
		
			
				|  |  | -   assign usb_ep[1].c.ep_mask       = 4'b1111;
 | 
	
		
			
				|  |  | -   assign usb_ep[2].c.ep_num        = 4'd2;
 | 
	
		
			
				|  |  | -   assign usb_ep[2].c.ep_mask       = 4'b1111;
 | 
	
		
			
				|  |  | -   assign usb_ep[3].c.ep_num        = 4'd3;
 | 
	
		
			
				|  |  | -   assign usb_ep[3].c.ep_mask       = 4'b1111;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   //-----------------------------------------------------------------
 | 
	
		
			
				|  |  | -   // Stream I/O
 | 
	
		
			
				|  |  | -   //-----------------------------------------------------------------
 | 
	
		
			
				|  |  | -   reg        inport_valid_q;
 | 
	
		
			
				|  |  | -   reg [7:0]  inport_data_q;
 | 
	
		
			
				|  |  | -   reg [10:0] inport_cnt_q;
 | 
	
		
			
				|  |  | -   reg	      outport_break_q;
 | 
	
		
			
				|  |  | +   wire		       start_of_frame_ws;
 | 
	
		
			
				|  |  | +   reg		       start_of_frame_q;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   always @ (posedge clk_i or posedge rst_i)
 | 
	
		
			
				|  |  | -     if (rst_i)
 | 
	
		
			
				|  |  | -       begin
 | 
	
		
			
				|  |  | -	  inport_valid_q  <= 1'b0;
 | 
	
		
			
				|  |  | -	  inport_data_q   <= 8'b0;
 | 
	
		
			
				|  |  | -       end
 | 
	
		
			
				|  |  | -     else if (inport_accept_o)
 | 
	
		
			
				|  |  | -       begin
 | 
	
		
			
				|  |  | -	  inport_valid_q <= inport_valid_i;
 | 
	
		
			
				|  |  | -	  inport_data_q  <= inport_data_i;
 | 
	
		
			
				|  |  | -       end
 | 
	
		
			
				|  |  | +   synchronizer #(.width(1))
 | 
	
		
			
				|  |  | +   sof_sync (
 | 
	
		
			
				|  |  | +	     .rst_n ( 1'b1 ),
 | 
	
		
			
				|  |  | +	     .clk   ( sys_clk ),
 | 
	
		
			
				|  |  | +	     .d     ( start_of_frame_w ),
 | 
	
		
			
				|  |  | +	     .q     ( start_of_frame_ws )
 | 
	
		
			
				|  |  | +	     );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   wire [10:0] max_packet_w   = usb_hs_w ? 11'd511 : 11'd63;
 | 
	
		
			
				|  |  | -   wire        inport_last_w  = !inport_valid_i || (inport_cnt_q == max_packet_w);
 | 
	
		
			
				|  |  | +   always @(posedge sys_clk)
 | 
	
		
			
				|  |  | +     start_of_frame_q <= start_of_frame_ws;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   always @ (posedge clk_i or posedge rst_i)
 | 
	
		
			
				|  |  | -     if (rst_i)
 | 
	
		
			
				|  |  | -       inport_cnt_q  <= 11'b0;
 | 
	
		
			
				|  |  | -     else if (inport_last_w && usb_ep[2].u.tx_data_accept)
 | 
	
		
			
				|  |  | -       inport_cnt_q  <= 11'b0;
 | 
	
		
			
				|  |  | -     else if (inport_valid_q && usb_ep[2].u.tx_data_accept)
 | 
	
		
			
				|  |  | -       inport_cnt_q  <= inport_cnt_q + 11'd1;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   assign usb_ep[2].d.tx_data_valid = inport_valid_q;
 | 
	
		
			
				|  |  | -   assign usb_ep[2].d.tx_ready      = inport_valid_q;
 | 
	
		
			
				|  |  | -   assign usb_ep[2].d.tx_data_strb  = inport_valid_q;
 | 
	
		
			
				|  |  | -   assign usb_ep[2].d.tx_data       = inport_data_q;
 | 
	
		
			
				|  |  | -   assign usb_ep[2].d.tx_data_last  = inport_last_w;
 | 
	
		
			
				|  |  | +   wire start_of_frame_s = start_of_frame_ws & ~start_of_frame_q;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   assign inport_accept_o     = !inport_valid_q | usb_ep[2].u.tx_data_accept;
 | 
	
		
			
				|  |  | +   tri0 [31:0]         rdata_chan[0:7];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   assign outport_valid_o      = usb_ep[2].u.rx_valid && usb_ep[2].uc.rx_strb;
 | 
	
		
			
				|  |  | -   assign outport_data_o       = usb_ep[2].uc.rx_data;
 | 
	
		
			
				|  |  | -   assign usb_ep[2].d.rx_space = outport_accept_i;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   always @(posedge clk_i or posedge rst_i)
 | 
	
		
			
				|  |  | -     if (rst_i)
 | 
	
		
			
				|  |  | -       outport_break_q <= 1'b0;
 | 
	
		
			
				|  |  | -     else
 | 
	
		
			
				|  |  | -       outport_break_q <= rx_break_q |
 | 
	
		
			
				|  |  | -			  (outport_break_q &
 | 
	
		
			
				|  |  | -			   ~setup_set_w &
 | 
	
		
			
				|  |  | -			   ~outport_valid_o &
 | 
	
		
			
				|  |  | -			   ~(inport_valid_q & usb_ep[2].u.tx_data_accept));
 | 
	
		
			
				|  |  | +   generate
 | 
	
		
			
				|  |  | +      genvar  cn;
 | 
	
		
			
				|  |  | +      for (cn = 0; cn < channels; cn++)
 | 
	
		
			
				|  |  | +	begin : chan
 | 
	
		
			
				|  |  | +	   usb_cdc_channel #(.data_ep_num ( cn*2+1 ),
 | 
	
		
			
				|  |  | +			     .intr_ep_num ( cn*2+2 ))
 | 
	
		
			
				|  |  | +	   cchan (
 | 
	
		
			
				|  |  | +		 .rst_n            ( rst_n ),
 | 
	
		
			
				|  |  | +		 .sys_clk          ( sys_clk ),
 | 
	
		
			
				|  |  | +		 .cpu_valid        ( cpu_valid_cdc & cpu_addr[6:4] == cn ),
 | 
	
		
			
				|  |  | +		 .cpu_addr         ( cpu_addr[3:2] ),
 | 
	
		
			
				|  |  | +		 .cpu_rdata        ( rdata_chan[cn] ),
 | 
	
		
			
				|  |  | +		 .cpu_wdata        ( cpu_wdata ),
 | 
	
		
			
				|  |  | +		 .cpu_wstrb        ( cpu_wstrb[0] ),
 | 
	
		
			
				|  |  | +		 .irq              ( irq[cn] ),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		 .clk_i            ( clk_i ),
 | 
	
		
			
				|  |  | +		 .rst_i            ( rst_i ),
 | 
	
		
			
				|  |  | +		 .data_ep          ( usb_ep[cn*2+1].dstr ),
 | 
	
		
			
				|  |  | +		 .intr_ep          ( usb_ep[cn*2+2].dstr ),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		 .usb_configured   ( configured_q ),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		 .recv_break_i     ( rx_break_r[cn] ),
 | 
	
		
			
				|  |  | +		 .recv_break_o     ( recv_break_o[cn] ),
 | 
	
		
			
				|  |  | +		 .start_of_frame_s ( start_of_frame_s )
 | 
	
		
			
				|  |  | +		 );
 | 
	
		
			
				|  |  | +	end // block: chan
 | 
	
		
			
				|  |  | +   endgenerate
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   assign outport_break_o  = outport_break_q;
 | 
	
		
			
				|  |  | +   assign cpu_rdata_cdc = rdata_chan[cpu_addr[6:4]];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  endmodule
 |