/* * ut_pkt_xclk.v * * USB Packet Receiver - Clock Domain Crossing * * vim: ts=4 sw=4 * * Copyright (C) 2022 Sylvain Munaut * SPDX-License-Identifier: CERN-OHL-P-2.0 */ `default_nettype none module ut_pkt_xclk ( // Input input wire pi_start, input wire pi_done_ok, input wire pi_done_err, input wire [3:0] pi_pid, input wire pi_is_sof, input wire pi_is_token, input wire pi_is_data, input wire pi_is_handshake, input wire [10:0] pi_frameno, input wire [6:0] pi_addr, input wire [3:0] pi_endp, input wire [7:0] pi_data, input wire pi_data_stb, input wire pi_clk, // Output output wire po_start, output wire po_done_ok, output wire po_done_err, output wire [3:0] po_pid, output wire po_is_sof, output wire po_is_token, output wire po_is_data, output wire po_is_handshake, output wire [10:0] po_frameno, output wire [6:0] po_addr, output wire [3:0] po_endp, output wire [7:0] po_data, output wire po_data_stb, input wire po_clk, // Reset input wire rst ); xclk_bus #( .WIDTH(8) ) xclk_start_I ( .in_stb (pi_start), .in_bus ({pi_pid, pi_is_sof, pi_is_token, pi_is_data, pi_is_handshake}), .in_clk (pi_clk), .out_stb (po_start), .out_bus ({po_pid, po_is_sof, po_is_token, po_is_data, po_is_handshake}), .out_clk (po_clk), .rst (rst) ); xclk_bus #( .WIDTH(11) ) xclk_ok_I ( .in_stb (pi_done_ok), .in_bus (pi_frameno), .in_clk (pi_clk), .out_stb (po_done_ok), .out_bus (po_frameno), .out_clk (po_clk), .rst (rst) ); assign po_addr = po_frameno[ 6:0]; assign po_endp = po_frameno[10:7]; xclk_strobe xclk_err_I ( .in_stb (pi_done_err), .in_clk (pi_clk), .out_stb (po_done_err), .out_clk (po_clk), .rst (rst) ); xclk_bus #( .WIDTH(8) ) xclk_data_I ( .in_stb (pi_data_stb), .in_bus (pi_data), .in_clk (pi_clk), .out_stb (po_data_stb), .out_bus (po_data), .out_clk (po_clk), .rst (rst) ); endmodule // ut_pkt_xclk module xclk_bus #( parameter integer WIDTH = 8, // auto-set parameter WL = WIDTH - 1 )( input wire in_stb, input wire [WL:0] in_bus, input wire in_clk, output reg out_stb, output reg [WL:0] out_bus, input wire out_clk, input wire rst ); reg src_tgl; reg [WL:0] src_bus; reg [1:0] dst_tgl; always @(posedge in_clk or posedge rst) if (rst) src_tgl <= 1'b0; else src_tgl <= src_tgl ^ in_stb; always @(posedge out_clk or posedge rst) if (rst) dst_tgl <= 2'b00; else dst_tgl <= { dst_tgl[0], src_tgl }; always @(posedge out_clk or posedge rst) if (rst) out_stb <= 1'b0; else out_stb <= ^dst_tgl[1:0]; always @(posedge in_clk) if (in_stb) src_bus <= in_bus; always @(posedge out_clk) out_bus <= ^dst_tgl[1:0] ? src_bus : out_bus; endmodule