域间数据传递之域外为慢速数据
域外慢速数据可以用事件来同步,具体参展王贞炎老师的《FPGA应用开发和仿真》4.5.4节。
这里给出一种Verilog实现方式。
sync_data.v
`timescale 1ns/100ps
module sync_data #(
parameter NUM_OF_BITS = 1,
parameter ASYNC_CLK = 1
) (
input in_clk,
input [NUM_OF_BITS-1:0] in_data,
input out_clk,
output reg [NUM_OF_BITS-1:0] out_data
);
generate
if (ASYNC_CLK == 1) begin
wire out_toggle;
wire in_toggle;
reg out_toggle_d1 = 1'b0;
reg in_toggle_d1 = 1'b0;
reg [NUM_OF_BITS-1:0] cdc_hold;
sync_bits i_sync_out (
.in_bits(in_toggle_d1),
.out_clk(out_clk),
.out_resetn(1'b1),
.out_bits(out_toggle)
);
sync_bits i_sync_in (
.in_bits(out_toggle_d1),
.out_clk(in_clk),
.out_resetn(1'b1),
.out_bits(in_toggle)
);
wire in_load = in_toggle == in_toggle_d1;
wire out_load = out_toggle ^ out_toggle_d1;
always @(posedge in_clk) begin
if (in_load == 1'b1) begin
cdc_hold <= in_data;
in_toggle_d1 <= ~in_toggle_d1;
end
end
always @(posedge out_clk) begin
if (out_load == 1'b1) begin
out_data <= cdc_hold;
end
out_toggle_d1 <= out_toggle;
end
end else begin
always @(*) begin
out_data <= in_data;
end
end
endgenerate
endmodule
sync_bits.v
/*
* Helper module for synchronizing bit signals from one clock domain to another.
* It uses the standard approach of 2 FF in series.
* Note, that while the module allows to synchronize multiple bits at once it is
* only able to synchronize multi-bit signals where at max one bit changes per
* clock cycle (e.g. a gray counter).
*/
`timescale 1ns/100ps
module sync_bits #(
// Number of bits to synchronize
parameter NUM_OF_BITS = 1,
// Whether input and output clocks are asynchronous, if 0 the synchronizer will
// be bypassed and the output signal equals the input signal.
parameter ASYNC_CLK = 1)(
input [NUM_OF_BITS-1:0] in_bits,
input out_resetn,
input out_clk,
output [NUM_OF_BITS-1:0] out_bits);
generate if (ASYNC_CLK == 1) begin
reg [NUM_OF_BITS-1:0] cdc_sync_stage1 = 'h0;
reg [NUM_OF_BITS-1:0] cdc_sync_stage2 = 'h0;
always @(posedge out_clk)
begin
if (out_resetn == 1'b0) begin
cdc_sync_stage1 <= 'b0;
cdc_sync_stage2 <= 'b0;
end else begin
cdc_sync_stage1 <= in_bits;
cdc_sync_stage2 <= cdc_sync_stage1;
end
end
assign out_bits = cdc_sync_stage2;
end else begin
assign out_bits = in_bits;
end endgenerate
endmodule