Added some stuff from modem and added formal
This commit is contained in:
70
cores/util/cdc/rtl/cdc_req_resp.v
Normal file
70
cores/util/cdc/rtl/cdc_req_resp.v
Normal file
@@ -0,0 +1,70 @@
|
||||
`timescale 1 ns/1 ps
|
||||
// =============================================================================
|
||||
// cdc_req_resp
|
||||
// Bidirectional channel made from two cdc_strobe_data mailboxes.
|
||||
// =============================================================================
|
||||
module cdc_req_resp #(
|
||||
parameter integer REQ_W = 32,
|
||||
parameter integer RESP_W = 32,
|
||||
parameter integer STABLE_SAMPLES = 2
|
||||
)(
|
||||
// Side A (e.g., JTAG/TCK)
|
||||
input wire a_clk,
|
||||
input wire a_rst,
|
||||
|
||||
input wire a_req_pulse,
|
||||
input wire [REQ_W-1:0] a_req_data,
|
||||
output wire a_req_busy,
|
||||
output wire a_req_accepted,
|
||||
|
||||
output wire a_resp_pulse,
|
||||
output wire [RESP_W-1:0] a_resp_data,
|
||||
|
||||
// Side B (e.g., system/i_clk)
|
||||
input wire b_clk,
|
||||
input wire b_rst,
|
||||
|
||||
output wire b_req_pulse,
|
||||
output wire [REQ_W-1:0] b_req_data,
|
||||
|
||||
input wire b_resp_pulse,
|
||||
input wire [RESP_W-1:0] b_resp_data,
|
||||
output wire b_resp_busy,
|
||||
output wire b_resp_accepted
|
||||
);
|
||||
|
||||
cdc_strobe_data #(
|
||||
.WIDTH(REQ_W),
|
||||
.STABLE_SAMPLES(STABLE_SAMPLES)
|
||||
) u_req (
|
||||
.s_clk(a_clk),
|
||||
.s_rst(a_rst),
|
||||
.s_pulse(a_req_pulse),
|
||||
.s_data(a_req_data),
|
||||
.s_busy(a_req_busy),
|
||||
.s_accepted(a_req_accepted),
|
||||
|
||||
.d_clk(b_clk),
|
||||
.d_rst(b_rst),
|
||||
.d_pulse(b_req_pulse),
|
||||
.d_data(b_req_data)
|
||||
);
|
||||
|
||||
cdc_strobe_data #(
|
||||
.WIDTH(RESP_W),
|
||||
.STABLE_SAMPLES(STABLE_SAMPLES)
|
||||
) u_resp (
|
||||
.s_clk(b_clk),
|
||||
.s_rst(b_rst),
|
||||
.s_pulse(b_resp_pulse),
|
||||
.s_data(b_resp_data),
|
||||
.s_busy(b_resp_busy),
|
||||
.s_accepted(b_resp_accepted),
|
||||
|
||||
.d_clk(a_clk),
|
||||
.d_rst(a_rst),
|
||||
.d_pulse(a_resp_pulse),
|
||||
.d_data(a_resp_data)
|
||||
);
|
||||
|
||||
endmodule
|
||||
130
cores/util/cdc/rtl/cdc_strobe_data.v
Normal file
130
cores/util/cdc/rtl/cdc_strobe_data.v
Normal file
@@ -0,0 +1,130 @@
|
||||
`timescale 1 ns/1 ps
|
||||
// =============================================================================
|
||||
// cdc_strobe_data
|
||||
// - One-deep mailbox for (strobe + data) crossing clock domains.
|
||||
// - Uses toggle req/ack with 2FF sync for toggles.
|
||||
// - Wide bus is held stable by source until ack, destination samples-until-stable.
|
||||
// =============================================================================
|
||||
module cdc_strobe_data #(
|
||||
parameter integer WIDTH = 32,
|
||||
parameter integer STABLE_SAMPLES = 2 // >=2 recommended
|
||||
)(
|
||||
// Source domain
|
||||
input wire s_clk,
|
||||
input wire s_rst, // async OK (posedge) if used consistently
|
||||
input wire s_pulse, // strobe (1+ cycles). Accepted when not busy.
|
||||
input wire [WIDTH-1:0] s_data,
|
||||
output wire s_busy, // 1 = mailbox full / waiting for ack
|
||||
output wire s_accepted, // 1-cycle pulse when we accepted s_pulse
|
||||
|
||||
// Destination domain
|
||||
input wire d_clk,
|
||||
input wire d_rst,
|
||||
output reg d_pulse, // 1-cycle pulse on new data
|
||||
output reg [WIDTH-1:0] d_data // updated when d_pulse asserted; held otherwise
|
||||
);
|
||||
|
||||
// ----------------------------
|
||||
// Source: hold + req toggle
|
||||
// ----------------------------
|
||||
reg [WIDTH-1:0] s_hold;
|
||||
reg s_req_tog;
|
||||
reg s_inflight;
|
||||
|
||||
// Ack toggle synchronized into source domain
|
||||
(* ASYNC_REG="TRUE" *) reg s_ack_sync1, s_ack_sync2;
|
||||
|
||||
assign s_busy = s_inflight;
|
||||
wire do_accept = s_pulse && !s_inflight;
|
||||
assign s_accepted = do_accept;
|
||||
|
||||
// d_ack_tog is generated in destination domain (declared below as reg)
|
||||
// and is synced here with 2FF.
|
||||
always @(posedge s_clk or posedge s_rst) begin
|
||||
if (s_rst) begin
|
||||
s_hold <= {WIDTH{1'b0}};
|
||||
s_req_tog <= 1'b0;
|
||||
s_inflight <= 1'b0;
|
||||
s_ack_sync1 <= 1'b0;
|
||||
s_ack_sync2 <= 1'b0;
|
||||
end else begin
|
||||
s_ack_sync1 <= d_ack_tog;
|
||||
s_ack_sync2 <= s_ack_sync1;
|
||||
|
||||
// clear inflight when ack matches current req toggle
|
||||
if (s_inflight && (s_ack_sync2 == s_req_tog))
|
||||
s_inflight <= 1'b0;
|
||||
|
||||
// accept new item
|
||||
if (do_accept) begin
|
||||
s_hold <= s_data;
|
||||
s_req_tog <= ~s_req_tog;
|
||||
s_inflight <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// ----------------------------
|
||||
// Destination: sync req toggle, sample-until-stable, then ack toggle
|
||||
// ----------------------------
|
||||
(* ASYNC_REG="TRUE" *) reg d_req_sync1, d_req_sync2;
|
||||
reg d_req_seen;
|
||||
|
||||
reg d_ack_tog;
|
||||
|
||||
reg [WIDTH-1:0] samp;
|
||||
reg [WIDTH-1:0] samp_prev;
|
||||
integer stable_cnt;
|
||||
reg capturing;
|
||||
|
||||
wire d_new_req = (d_req_sync2 != d_req_seen);
|
||||
|
||||
always @(posedge d_clk or posedge d_rst) begin
|
||||
if (d_rst) begin
|
||||
d_req_sync1 <= 1'b0;
|
||||
d_req_sync2 <= 1'b0;
|
||||
d_req_seen <= 1'b0;
|
||||
d_ack_tog <= 1'b0;
|
||||
|
||||
d_pulse <= 1'b0;
|
||||
d_data <= {WIDTH{1'b0}};
|
||||
|
||||
samp <= {WIDTH{1'b0}};
|
||||
samp_prev <= {WIDTH{1'b0}};
|
||||
stable_cnt <= 0;
|
||||
capturing <= 1'b0;
|
||||
end else begin
|
||||
d_pulse <= 1'b0;
|
||||
|
||||
d_req_sync1 <= s_req_tog;
|
||||
d_req_sync2 <= d_req_sync1;
|
||||
|
||||
if (d_new_req && !capturing) begin
|
||||
capturing <= 1'b1;
|
||||
stable_cnt <= 0;
|
||||
samp_prev <= s_hold;
|
||||
samp <= s_hold;
|
||||
end else if (capturing) begin
|
||||
samp <= s_hold;
|
||||
|
||||
if (samp == samp_prev) begin
|
||||
if (stable_cnt < (STABLE_SAMPLES-1))
|
||||
stable_cnt <= stable_cnt + 1;
|
||||
else begin
|
||||
// accept
|
||||
d_data <= samp;
|
||||
d_pulse <= 1'b1;
|
||||
d_req_seen <= d_req_sync2;
|
||||
d_ack_tog <= ~d_ack_tog;
|
||||
capturing <= 1'b0;
|
||||
end
|
||||
end else begin
|
||||
stable_cnt <= 0;
|
||||
end
|
||||
|
||||
samp_prev <= samp;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user