3 // Source-synchronous receiver
4 // Assumes both clocks are at the same rate
5 // Relative clock phase is
9 // The output will come several cycles later than the input
11 // This should synthesize efficiently in Xilinx distributed ram cells,
12 // which is why we use a buffer depth of 16
14 // FIXME Async reset on rxclk side?
22 input [WIDTH-1:0] data_in,
23 output [WIDTH-1:0] data_out,
24 output reg clock_present);
26 wire [3:0] rd_addr, wr_addr;
29 reg [WIDTH-1:0] buffer [0:15];
30 always @(posedge rxclk)
31 buffer[wr_addr] <= data_in;
33 assign data_out = buffer[rd_addr];
35 // Write address generation
37 always @(posedge rxclk or posedge rst)
41 wr_counter <= wr_counter + 1;
43 assign wr_addr = {wr_counter[3], ^wr_counter[3:2], ^wr_counter[2:1], ^wr_counter[1:0]};
45 // Read Address generation
46 wire [3:0] wr_ctr_sys, diff, abs_diff;
47 reg [3:0] wr_addr_sys_d1, wr_addr_sys_d2;
50 assign rd_addr = {rd_counter[3], ^rd_counter[3:2], ^rd_counter[2:1], ^rd_counter[1:0]};
52 always @(posedge sysclk)
53 wr_addr_sys_d1 <= wr_addr;
55 always @(posedge sysclk)
56 wr_addr_sys_d2 <= wr_addr_sys_d1;
58 assign wr_ctr_sys = {wr_addr_sys_d2[3],^wr_addr_sys_d2[3:2],^wr_addr_sys_d2[3:1],^wr_addr_sys_d2[3:0]};
60 assign diff = wr_ctr_sys - rd_counter;
61 assign abs_diff = diff[3] ? (~diff+1) : diff;
63 always @(posedge sysclk)
79 rd_counter <= rd_counter + 1;