diff options
Diffstat (limited to 'rtl/src/verilog/cdc_bus_pulse.v')
-rw-r--r-- | rtl/src/verilog/cdc_bus_pulse.v | 216 |
1 files changed, 108 insertions, 108 deletions
diff --git a/rtl/src/verilog/cdc_bus_pulse.v b/rtl/src/verilog/cdc_bus_pulse.v index 104bfa5..631506c 100644 --- a/rtl/src/verilog/cdc_bus_pulse.v +++ b/rtl/src/verilog/cdc_bus_pulse.v @@ -1,114 +1,114 @@ -`timescale 1ns / 1ps
-
-module cdc_bus_pulse
- (
- src_clk, src_din, src_req,
- dst_clk, dst_dout, dst_pulse
- );
-
- /* This module is based on design suggested on page 27 of an article titled
- "Clock Domain Crossing (CDC) Design & Verification Techniques Using SystemVerilog"
- by Clifford E. Cummings (Sunburst Design, Inc.)
- */
-
- //
- // Parameters
- //
- parameter DATA_WIDTH = 32; // width of data bus
-
-
- //
- // Ports
- //
- input wire src_clk; // source domain clock
- input wire [DATA_WIDTH-1:0] src_din; // data from source clock domain
- input wire src_req; // start transfer pulse from source clock domain
-
- input wire dst_clk; // destination domain clock
- output wire [DATA_WIDTH-1:0] dst_dout; // data to destination clock domain
- output wire dst_pulse; // transfer done pulse to destination clock domain
-
-
- //
- // Source Side Registers
- //
- reg src_ff = 1'b0; // transfer request flag
- reg [DATA_WIDTH-1:0] src_latch = {DATA_WIDTH{1'bX}}; // source data buffer
-
-
- //
- // Source Request Handler
- //
- always @(posedge src_clk)
- //
- if (src_req) begin // transfer request pulse?
- src_ff <= ~src_ff; // toggle transfer request flag...
- src_latch <= src_din; // ... and capture data in source buffer
- end
-
-
- //
- // Source -> Destination Flag Sync Logic
- //
-
- /* ISE may decide to infer SRL here, so we explicitly instantiate slice registers. */
-
- wire flag_sync_first; // first FF output
- wire flag_sync_second; // second FF output
- wire flag_sync_third; // third FF output
- wire flag_sync_pulse; // flag toggle detector output
-
- FDCE ff_sync_first
- (
- .C (dst_clk),
+`timescale 1ns / 1ps + +module cdc_bus_pulse + ( + src_clk, src_din, src_req, + dst_clk, dst_dout, dst_pulse + ); + + /* This module is based on design suggested on page 27 of an article titled + "Clock Domain Crossing (CDC) Design & Verification Techniques Using SystemVerilog" + by Clifford E. Cummings (Sunburst Design, Inc.) + */ + + // + // Parameters + // + parameter DATA_WIDTH = 32; // width of data bus + + + // + // Ports + // + input wire src_clk; // source domain clock + input wire [DATA_WIDTH-1:0] src_din; // data from source clock domain + input wire src_req; // start transfer pulse from source clock domain + + input wire dst_clk; // destination domain clock + output wire [DATA_WIDTH-1:0] dst_dout; // data to destination clock domain + output wire dst_pulse; // transfer done pulse to destination clock domain + + + // + // Source Side Registers + // + reg src_ff = 1'b0; // transfer request flag + reg [DATA_WIDTH-1:0] src_latch = {DATA_WIDTH{1'bX}}; // source data buffer + + + // + // Source Request Handler + // + always @(posedge src_clk) + // + if (src_req) begin // transfer request pulse? + src_ff <= ~src_ff; // toggle transfer request flag... + src_latch <= src_din; // ... and capture data in source buffer + end + + + // + // Source -> Destination Flag Sync Logic + // + + /* ISE may decide to infer SRL here, so we explicitly instantiate slice registers. */ + + wire flag_sync_first; // first FF output + wire flag_sync_second; // second FF output + wire flag_sync_third; // third FF output + wire flag_sync_pulse; // flag toggle detector output + + FDCE ff_sync_first + ( + .C (dst_clk), .D (src_ff), // capture flag from another clock domain - .Q (flag_sync_first), // metastability can occur here
- .CLR (1'b0),
+ .Q (flag_sync_first), // metastability can occur here + .CLR (1'b0), .CE (1'b1) - );
- FDCE ff_sync_second
- (
- .C (dst_clk),
+ ); + FDCE ff_sync_second + ( + .C (dst_clk), .D (flag_sync_first), // synchronize captured flag to remove metastability - .Q (flag_sync_second), // and pass it to another flip-flop
- .CLR (1'b0),
+ .Q (flag_sync_second), // and pass it to another flip-flop + .CLR (1'b0), .CE (1'b1) - );
- FDCE ff_sync_third
- (
- .C (dst_clk),
+ ); + FDCE ff_sync_third + ( + .C (dst_clk), .D (flag_sync_second), // delay synchronized flag in another flip-flip, because we need - .Q (flag_sync_third), // two synchronized flag values (current and delayed) to detect its change
- .CLR (1'b0),
+ .Q (flag_sync_third), // two synchronized flag values (current and delayed) to detect its change + .CLR (1'b0), .CE (1'b1) - );
-
- // when delayed flag value differs from its current value, it was changed
- // by the source side, so there must have been a transfer request
- assign flag_sync_pulse = flag_sync_second ^ flag_sync_third;
-
-
- //
- // Destination Side Registers
- //
- reg dst_pulse_reg = 1'b0; // transfer done flag
- reg [DATA_WIDTH-1:0] dst_latch = {DATA_WIDTH{1'bX}}; // destination data buffer
-
- assign dst_pulse = dst_pulse_reg;
- assign dst_dout = dst_latch;
-
- //
- // Destination Request Handler
- //
- always @(posedge dst_clk) begin
- //
- dst_pulse_reg <= flag_sync_pulse; // generate pulse if flag change was detected
- //
- if (flag_sync_pulse) dst_latch <= src_latch; // by the time destination side receives synchronized
- // // flag value, data should be stable, we can safely
- // // capture and store it in the destination buffer
- //
- end
-
-
-endmodule
+ ); + + // when delayed flag value differs from its current value, it was changed + // by the source side, so there must have been a transfer request + assign flag_sync_pulse = flag_sync_second ^ flag_sync_third; + + + // + // Destination Side Registers + // + reg dst_pulse_reg = 1'b0; // transfer done flag + reg [DATA_WIDTH-1:0] dst_latch = {DATA_WIDTH{1'bX}}; // destination data buffer + + assign dst_pulse = dst_pulse_reg; + assign dst_dout = dst_latch; + + // + // Destination Request Handler + // + always @(posedge dst_clk) begin + // + dst_pulse_reg <= flag_sync_pulse; // generate pulse if flag change was detected + // + if (flag_sync_pulse) dst_latch <= src_latch; // by the time destination side receives synchronized + // // flag value, data should be stable, we can safely + // // capture and store it in the destination buffer + // + end + + +endmodule |