1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
//
// Copyright 2025 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: ctrlport_if_clk_cross
//
// Description:
//
// Crosses control-port interface between different clock domains.
//
module ctrlport_if_clk_cross
(
ctrlport_if.slave s_ctrlport,
ctrlport_if.master m_ctrlport
);
import ctrlport_pkg::*;
//---------------------------------------------------------------------------
// Slave to Master Clock Crossing (Request)
//---------------------------------------------------------------------------
ctrlport_request_t m_req_hs;
logic m_req_hs_valid;
// Busy flag can be ignored as the response handshake takes at least the same
// amount of cycles to transfer the response as this handshake instance needs
// to release the busy flag as they are configured with the same amount of
// synchronization stages. Furthermore the ctrlport protocol just allows for
// one transaction to be active at the same time. A request can only be issued
// once the response is provided.
handshake #(
.WIDTH($bits(ctrlport_request_t))
) req_handshake_inst (
.clk_a(s_ctrlport.clk),
.rst_a(s_ctrlport.rst),
.valid_a((s_ctrlport.req.rd | s_ctrlport.req.wr) & ~s_ctrlport.rst),
.data_a(s_ctrlport.req),
.busy_a(),
.clk_b(m_ctrlport.clk),
.valid_b(m_req_hs_valid),
.data_b(m_req_hs)
);
always_comb begin
m_ctrlport.req = m_req_hs;
// mask read and write flags
m_ctrlport.req.wr = m_req_hs.wr & m_req_hs_valid & ~m_ctrlport.rst;
m_ctrlport.req.rd = m_req_hs.rd & m_req_hs_valid & ~m_ctrlport.rst;
end
//---------------------------------------------------------------------------
// Master to Slave Clock Crossing (Response)
//---------------------------------------------------------------------------
ctrlport_response_t s_resp_hs;
logic s_resp_hs_valid;
// Busy flag can be ignored as the request handshake takes at least the same
// amount of cycles to transfer the request as this handshake instance needs
// to release the busy flag as they are configured with the same amount of
// synchronization stages. Furthermore the ctrlport protocol just allows for
// one transaction to be active at the same time. A response can only be
// issued once the request is available.
handshake #(
.WIDTH($bits(ctrlport_response_t))
) resp_handshake_inst (
.clk_a(m_ctrlport.clk),
.rst_a(m_ctrlport.rst),
.valid_a(m_ctrlport.resp.ack & ~m_ctrlport.rst),
.data_a(m_ctrlport.resp),
.busy_a(),
.clk_b(s_ctrlport.clk),
.valid_b(s_resp_hs_valid),
.data_b(s_resp_hs)
);
always_comb begin
s_ctrlport.resp = s_resp_hs;
s_ctrlport.resp.ack = s_resp_hs.ack & s_resp_hs_valid & ~s_ctrlport.rst;
end
endmodule
|