x393  1.0
FPGAcodeforElphelNC393camera
fifo_cross_clocks.v
Go to the documentation of this file.
1 
39 `timescale 1ns/1ps
40 
42 #(
43  parameter integer DATA_WIDTH=16,
44  parameter integer DATA_DEPTH=4 // >=3
45 ) (
46  input rst, // async reset, active high (global)
47  input rrst, // @ posedge rclk - sync reset
48  input wrst, // @ posedge wclk - sync reset
49  input rclk, // read clock - positive edge
50  input wclk, // write clock - positive edge
51  input we, // write enable
52  input re, // read enable
53  input [DATA_WIDTH-1:0] data_in, // input data
54  output [DATA_WIDTH-1:0] data_out, // output data
55  output nempty, // FIFO has some data (sync to rclk)
56  output half_empty // FIFO half full (wclk) -(not more than 5/8 full)
57  );
58  localparam integer DATA_2DEPTH=(1<<DATA_DEPTH)-1;
59  reg [DATA_WIDTH-1:0] ram [0:DATA_2DEPTH];
60  reg [DATA_DEPTH-1:0] raddr;
61  reg [DATA_DEPTH-1:0] waddr;
62  reg [DATA_DEPTH-1:0] waddr_gray; //SuppressThisWarning ISExst VivadoSynthesis : MSB(waddr_gray) == MSB(waddr)
64  wire [DATA_DEPTH-1:0] waddr_plus1 = waddr +1;
66 
67  wire [DATA_DEPTH-1:0] raddr_gray = raddr ^ {1'b0,raddr[DATA_DEPTH-1:1]};
68  wire [DATA_DEPTH-1:0] raddr_plus1 = raddr +1;
70  reg [2:0] raddr_gray_top3; //SuppressThisWarning ISExst VivadoSynthesis : MSB(raddr_gray_top3) == MSB(raddr)
72  wire [2:0] raddr_top3_wclk = {
77  wire [2:0] addr_diff=waddr_top3[2:0]-raddr_top3_wclk[2:0];
78  // half-empty does not need to be precise, it uses 3 MSBs of the write address
79  // converting to Gray code (easy) and then back (can not be done parallel easily).
80  // Comparing to 1/8'th of the depth with one-bit Gray code error results in uncertainty
81  // of +/-1/8, so half_empty means "no more than 5/8 full"
82  assign half_empty=~addr_diff[2];
83  // False positive in nempty can only happen if
84  // a) it is transitioning from empty to non-empty due to we pulse
85  // b) it is transitioning to overrun - too bad already
86  // false negative - OK, just wait for the next rclk
87 // assign nempty=waddr_gray_rclk != raddr_gray;
88 // assign nempty=waddr_gray_rclk[3:0] != raddr_gray[3:0];
89  assign nempty= (waddr_gray_rclk[3:0] ^ raddr_gray[3:0]) != 4'b0;
90  assign data_out=ram[raddr];
91  always @ (posedge wclk or posedge rst) begin
92  if (rst) waddr <= 0;
93  else if (wrst) waddr <= 0;
94  else if (we) waddr <= waddr_plus1;
95 
96  if (rst) waddr_gray <= 0;
97  else if (wrst) waddr_gray <= 0;
98  else if (we) waddr_gray [3:0] <= waddr_plus1_gray[3:0];
99 
100  end
101 
102  always @ (posedge rclk or posedge rst) begin
103 // making rrst set FIFO to empty regardless of current waddr (write should be stopped)
104  if (rst) raddr <= waddr; // 0;
105  else if (rrst) raddr <= waddr; // 0;
106  else if (re) raddr <= raddr_plus1;
107 
108  if (rst) raddr_gray_top3 <= waddr[DATA_DEPTH-1 -: 3] ^ {1'b0,waddr[DATA_DEPTH-1 -: 2]}; // 0;
109  else if (rrst) raddr_gray_top3 <= waddr[DATA_DEPTH-1 -: 3] ^ {1'b0,waddr[DATA_DEPTH-1 -: 2]}; // 0;
111  end
112 
113  always @ (posedge rclk) begin
114  waddr_gray_rclk[3:0] <= waddr_gray[3:0];
115 
116  end
117 
118  always @ (posedge wclk) begin
120  if (we) ram[waddr] <= data_in;
121  end
122 
123 endmodule
124 
10415raddr_graywire[DATA_DEPTH-1:0]
10419raddr_gray_top3_wclkreg[2:0]
10420raddr_top3_wclkwire[2:0]
[DATA_WIDTH-1:0] 10404data_out
integer 10394DATA_WIDTH16
10409raddrreg[DATA_DEPTH-1:0]
10412waddr_gray_rclkreg[DATA_DEPTH-1:0]
10416raddr_plus1wire[DATA_DEPTH-1:0]
10417raddr_plus1_gray_top3wire[2:0]
[0:DATA_2DEPTH] 10408ramreg[DATA_WIDTH-1:0]
10411waddr_grayreg[DATA_DEPTH-1:0]
[DATA_WIDTH-1:0] 10403data_in
10414waddr_plus1_graywire[DATA_DEPTH-1:0]
integer 10407DATA_2DEPTH(1<<DATA_DEPTH)-1
10410waddrreg[DATA_DEPTH-1:0]
10418raddr_gray_top3reg[2:0]
integer 10395DATA_DEPTH4
10413waddr_plus1wire[DATA_DEPTH-1:0]