1`timescale 1ns / 1ps 2/* 3 * This software is Copyright (c) 2016 Denis Burykin 4 * [denis_burykin yahoo com], [denis-burykin2014 yandex ru] 5 * and it is hereby released to the general public under the following terms: 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted. 8 * 9 */ 10 11// ********************************************************* 12// 13// Clock Domain Crossing Register 14// 15// * assumes frequency relation: wr_clk <= rd_clk <= wr_clk X 2 16// (write frequency is less or equal) 17// 18// ********************************************************* 19 20module cdc_reg #( 21 parameter WIDTH = -1 22 )( 23 input wr_clk, 24 input [WIDTH-1:0] din, 25 input wr_en, 26 output reg full = 0, 27 28 input rd_clk, 29 output reg [WIDTH-1:0] dout = {WIDTH{1'b0}}, 30 input rd_en, 31 output empty 32 ); 33 34 always @(posedge wr_clk) begin 35 if (~full) begin 36 if (wr_en) begin 37 dout <= din; 38 full <= 1; 39 end 40 end 41 else if (rd_en_sync) 42 full <= 0; 43 end 44 45 sync_sig sync_full(.sig(full), .clk(rd_clk), .out(full_sync)); 46 47 sync_short_sig #(.CLK1(1)) sync_rd_en(.sig(rd_en), .clk(wr_clk), .out(rd_en_sync)); 48 49 // EMPTY considerations. 50 // must react on rd_en in 1 cycle - requires to run on rd_clk clock 51 // after read, consider FULL flag synchronization 52 localparam EMPTY_STATE_INIT = 0, 53 EMPTY_STATE_CAN_READ = 1, 54 EMPTY_STATE_READ_COMPLETE = 2; 55 56 (* FSM_EXTRACT="true" *) 57 reg [1:0] empty_state = EMPTY_STATE_INIT; 58 59 always @(posedge rd_clk) 60 case (empty_state) 61 EMPTY_STATE_INIT: 62 if (full_sync) 63 empty_state <= EMPTY_STATE_CAN_READ; 64 65 EMPTY_STATE_CAN_READ: 66 if (rd_en) 67 empty_state <= EMPTY_STATE_READ_COMPLETE; 68 69 EMPTY_STATE_READ_COMPLETE: 70 if (~full_sync) 71 empty_state <= EMPTY_STATE_INIT; 72 73 endcase 74 75 assign empty = empty_state == EMPTY_STATE_CAN_READ ? 1'b0 : 1'b1; 76 77 78endmodule 79 80 81// ********************************************************* 82// 83// Clock Domain Crossing Register - Improved version 84// 85// * Any frequency relation 86// * For good throughput, use a FIFO 87// 88// ********************************************************* 89 90module xdc_reg #( 91 parameter WIDTH = -1 92 )( 93 input wr_clk, 94 input [WIDTH-1:0] din, 95 input wr_en, 96 output reg full = 0, 97 98 input rd_clk, 99 output reg [WIDTH-1:0] dout = {WIDTH{1'b0}}, 100 input rd_en, 101 output empty 102 ); 103 104 always @(posedge wr_clk) begin 105 if (~full) begin 106 if (wr_en) begin 107 dout <= din; 108 full <= 1; 109 end 110 end 111 else if (rd_en_sync) 112 full <= 0; 113 end 114 115 sync_pulse sync_full(.wr_clk(wr_clk), .sig(full), .busy(), .rd_clk(rd_clk), .out(full_sync)); 116 117 sync_pulse sync_rd_en(.wr_clk(rd_clk), .sig(rd_en), .busy(), .rd_clk(wr_clk), .out(rd_en_sync)); 118 119 localparam EMPTY_STATE_CAN_READ = 0, 120 EMPTY_STATE_READ_COMPLETE = 1; 121 122 //(* FSM_EXTRACT="true" *) 123 reg empty_state = EMPTY_STATE_CAN_READ; 124 125 always @(posedge rd_clk) 126 case (empty_state) 127 EMPTY_STATE_CAN_READ: 128 if (rd_en & full_sync) 129 empty_state <= EMPTY_STATE_READ_COMPLETE; 130 131 EMPTY_STATE_READ_COMPLETE: 132 if (~full_sync) 133 empty_state <= EMPTY_STATE_CAN_READ; 134 135 endcase 136 137 assign empty = empty_state == EMPTY_STATE_CAN_READ & full_sync ? 1'b0 : 1'b1; 138 139endmodule 140