mirror of
https://github.com/retroSoC/common.git
synced 2026-11-04 22:32:37 +00:00
180 lines
5.5 KiB
Systemverilog
180 lines
5.5 KiB
Systemverilog
// Copyright 2018 ETH Zurich and University of Bologna.
|
|
//
|
|
// Copyright and related rights are licensed under the Solderpad Hardware
|
|
// License, Version 0.51 (the "License"); you may not use this file except in
|
|
// compliance with the License. You may obtain a copy of the License at
|
|
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
|
// or agreed to in writing, software, hardware and materials distributed under
|
|
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations under the License.
|
|
//
|
|
// Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
|
|
//
|
|
// -- Adaptable modifications are redistributed under compatible License --
|
|
//
|
|
// Copyright (c) 2023 Beijing Institute of Open Source Chip
|
|
// common is licensed under Mulan PSL v2.
|
|
// You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
// You may obtain a copy of Mulan PSL v2 at:
|
|
// http://license.coscl.org.cn/MulanPSL2
|
|
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
// See the Mulan PSL v2 for more details.
|
|
|
|
`ifndef INC_CDC_TWOPHASE_SV
|
|
`define INC_CDC_TWOPHASE_SV
|
|
|
|
`include "register.sv"
|
|
`include "cdc_sync.sv"
|
|
|
|
module cdc_2phase #(
|
|
parameter int DATA_WIDTH = 32
|
|
) (
|
|
input logic src_clk_i,
|
|
input logic src_rst_n_i,
|
|
input logic [DATA_WIDTH-1:0] src_data_i,
|
|
input logic src_valid_i,
|
|
output logic src_ready_o,
|
|
|
|
input logic dst_clk_i,
|
|
input logic dst_rst_n_i,
|
|
output logic [DATA_WIDTH-1:0] dst_data_o,
|
|
output logic dst_valid_o,
|
|
input logic dst_ready_i
|
|
);
|
|
|
|
logic s_async_req;
|
|
logic s_async_ack;
|
|
logic [DATA_WIDTH-1:0] s_async_data;
|
|
|
|
cdc_2phase_src #(DATA_WIDTH) u_cdc_2phase_src (
|
|
.clk_i (src_clk_i),
|
|
.rst_n_i (src_rst_n_i),
|
|
.data_i (src_data_i),
|
|
.valid_i (src_valid_i),
|
|
.ready_o (src_ready_o),
|
|
.async_req_o (s_async_req),
|
|
.async_ack_i (s_async_ack),
|
|
.async_data_o(s_async_data)
|
|
);
|
|
|
|
cdc_2phase_dst #(DATA_WIDTH) u_cdc_2phase_dst (
|
|
.clk_i (dst_clk_i),
|
|
.rst_n_i (dst_rst_n_i),
|
|
.data_o (dst_data_o),
|
|
.valid_o (dst_valid_o),
|
|
.ready_i (dst_ready_i),
|
|
.async_req_i (s_async_req),
|
|
.async_ack_o (s_async_ack),
|
|
.async_data_i(s_async_data)
|
|
);
|
|
|
|
endmodule
|
|
|
|
module cdc_2phase_src #(
|
|
parameter int DATA_WIDTH = 32
|
|
) (
|
|
input logic clk_i,
|
|
input logic rst_n_i,
|
|
input logic [DATA_WIDTH-1:0] data_i,
|
|
input logic valid_i,
|
|
output logic ready_o,
|
|
output logic async_req_o,
|
|
input logic async_ack_i,
|
|
output logic [DATA_WIDTH-1:0] async_data_o
|
|
);
|
|
|
|
logic s_req_src_d, s_req_src_q;
|
|
logic s_ack_src_d, s_ack_src_q;
|
|
logic s_ack_q;
|
|
logic [DATA_WIDTH-1:0] s_data_src_d, s_data_src_q;
|
|
|
|
// The req_src and data_src registers change when a new data item is accepted.
|
|
assign s_req_src_d = (valid_i && ready_o) ? ~s_req_src_q : s_req_src_q;
|
|
dffr #(1) u_req_src_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_req_src_d,
|
|
s_req_src_q
|
|
);
|
|
|
|
assign s_data_src_d = (valid_i && ready_o) ? data_i : s_data_src_q;
|
|
dffr #(DATA_WIDTH) u_data_src_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_data_src_d,
|
|
s_data_src_q
|
|
);
|
|
|
|
cdc_sync #(2, 1) u_ack_sync (
|
|
clk_i,
|
|
rst_n_i,
|
|
async_ack_i,
|
|
s_ack_q
|
|
);
|
|
|
|
assign ready_o = (s_req_src_q == s_ack_q);
|
|
assign async_req_o = s_req_src_q;
|
|
assign async_data_o = s_data_src_q;
|
|
|
|
endmodule
|
|
|
|
module cdc_2phase_dst #(
|
|
parameter int DATA_WIDTH = 32
|
|
) (
|
|
input logic rst_n_i,
|
|
input logic clk_i,
|
|
output logic [DATA_WIDTH-1:0] data_o,
|
|
output logic valid_o,
|
|
input logic ready_i,
|
|
input logic async_req_i,
|
|
output logic async_ack_o,
|
|
input logic [DATA_WIDTH-1:0] async_data_i
|
|
);
|
|
|
|
|
|
logic r_req_dst_q, r_req_q0, r_req_q1;
|
|
logic s_ack_dst_d, s_ack_dst_q;
|
|
logic [DATA_WIDTH-1:0] s_data_dst_d, s_data_dst_q;
|
|
|
|
// The ack_dst register changes when a new data item is accepted.
|
|
assign s_ack_dst_d = (valid_o && ready_i) ? ~s_ack_dst_q : s_ack_dst_q;
|
|
dffr #(1) u_ack_dst_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_ack_dst_d,
|
|
s_ack_dst_q
|
|
);
|
|
|
|
// The data_dst register changes when a new data item is presented. This is
|
|
// indicated by the async_req line changing levels.
|
|
assign s_data_dst_d = (r_req_q0 != r_req_q1 && !valid_o) ? async_data_i : s_data_dst_q;
|
|
dffr #(DATA_WIDTH) u_data_dst_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_data_dst_d,
|
|
s_data_dst_q
|
|
);
|
|
|
|
// The req_dst and req registers act as synchronization stages.
|
|
always_ff @(posedge clk_i or negedge rst_n_i) begin
|
|
if (!rst_n_i) begin
|
|
r_req_dst_q <= '0;
|
|
r_req_q0 <= '0;
|
|
r_req_q1 <= '0;
|
|
end else begin
|
|
r_req_dst_q <= async_req_i;
|
|
r_req_q0 <= r_req_dst_q;
|
|
r_req_q1 <= r_req_q0;
|
|
end
|
|
end
|
|
|
|
assign valid_o = (s_ack_dst_q != r_req_q1);
|
|
assign data_o = s_data_dst_q;
|
|
assign async_ack_o = s_ack_dst_q;
|
|
|
|
endmodule
|
|
`endif
|