xilinx_async_fifo.sv (3770B)
1 // Copyright 2014 Brian Swetland <swetland@frotz.net> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 `timescale 1ns/1ps 16 17 // reset in synchronous with wrclk 18 // on reset=1, active will go low on the next clock 19 // active will return high once the reset is complete 20 // reset will take a bit longer than 12 wrclk or rdclk 21 // (whichever is slower) 22 23 (* keep_hierarchy = "yes" *) 24 module xilinx_async_fifo( 25 input wrclk, 26 input rdclk, 27 input reset, 28 29 input [WIDTH-1:0]wr_data, 30 input wr_en, 31 32 input rd_en, 33 output [WIDTH-1:0]rd_data, 34 35 output o_empty, 36 output o_ready, // can absorb >= 16 writes 37 output o_active 38 ); 39 40 parameter WIDTH = 16; 41 42 wire fifo_res, fifo_act; 43 44 fifo_reset fifo_reset_0( 45 .clk1(wrclk), 46 .i_res(reset), 47 .clk2(rdclk), 48 .o_res(fifo_res), 49 .o_act(fifo_act) 50 ); 51 52 wire [31:0]do_data, di_data; 53 wire almostfull; 54 assign o_ready = ~almostfull; 55 56 assign o_active = fifo_act; 57 assign rd_data = do_data[WIDTH-1:0]; 58 assign di_data[WIDTH-1:0] = wr_data; 59 60 FIFO18E1 #( 61 .ALMOST_EMPTY_OFFSET(13'h80), 62 .ALMOST_FULL_OFFSET(13'h80), // TODO 63 .DATA_WIDTH(36), 64 .DO_REG(1), 65 .EN_SYN("FALSE"), 66 .FIFO_MODE("FIFO18_36"), 67 .FIRST_WORD_FALL_THROUGH("TRUE"), 68 .INIT(32'h0), 69 .SIM_DEVICE("7SERIES"), 70 .SRVAL(36'h0) 71 ) fifo ( 72 .DO(do_data), 73 .DOP(), 74 .ALMOSTEMPTY(), 75 .ALMOSTFULL(almostfull), 76 .EMPTY(o_empty), 77 .FULL(), 78 .RDCOUNT(), 79 .RDERR(), 80 .WRCOUNT(), 81 .WRERR(), 82 .RDCLK(rdclk), 83 .RDEN(fifo_act & rd_en), 84 .RST(fifo_res), 85 .WRCLK(wrclk), 86 .WREN(fifo_act & wr_en), 87 .DI(di_data), 88 .DIP(), 89 .REGCE(), 90 .RSTREG() 91 ); 92 93 endmodule 94 95 96 // on i_res (sync w/ clk1): 97 // 1. o_res will go high, i_act will go low 98 // 2. after at least 6 cycles of clk1 and clk2, o_res will go high 99 // 2. after at least 6 more cycles of clk1 and clk2, o_act will go high 100 101 (* keep_hierarchy = "yes" *) 102 module fifo_reset( 103 input clk1, 104 input clk2, 105 input i_res, 106 output reg o_res = 0, 107 output reg o_act = 1 108 ); 109 110 typedef enum { IDLE, RESET0, RESET1, WAIT } state_t; 111 state_t state1 = IDLE; 112 state_t next_state1; 113 reg [5:0]shift1 = 0; 114 reg [5:0]next_shift1; 115 116 // signal from clk1 domain to clk2 117 reg dat = 0; 118 reg next_dat; 119 120 reg next_res; 121 reg next_act; 122 123 // return from clk2 domain (after 6bit sr) 124 reg ack; 125 126 always_comb begin 127 next_state1 = state1; 128 next_shift1 = shift1; 129 next_dat = dat; 130 next_res = o_res; 131 next_act = o_act; 132 case (state1) 133 IDLE: begin 134 if (i_res) begin 135 next_act = 0; 136 next_state1 = RESET0; 137 end 138 end 139 RESET0: begin 140 next_res = 1; 141 next_state1 = RESET1; 142 next_shift1 = 6'b111111; 143 next_dat = 1; 144 end 145 RESET1: begin 146 next_shift1 = { 1'b0, shift1[5:1] }; 147 if ((shift1[0] == 0) && (ack==1)) begin 148 next_res = 0; 149 next_state1 = WAIT; 150 next_dat = 0; 151 next_shift1 = 6'b111111; 152 end 153 end 154 WAIT: begin 155 next_shift1 = { 1'b0, shift1[5:1] }; 156 if ((shift1[0] == 0) && (ack==0)) begin 157 next_act = 1; 158 next_state1 = IDLE; 159 end 160 end 161 endcase 162 end 163 164 always_ff @(posedge clk1) begin 165 state1 <= next_state1; 166 shift1 <= next_shift1; 167 dat <= next_dat; 168 o_res <= next_res; 169 o_act <= next_act; 170 end 171 172 wire shift2_in; 173 reg [5:0]shift2 = 0; 174 175 always @(posedge clk2) 176 shift2 <= { shift2_in, shift2[5:1] }; 177 178 sync_oneway sync0( 179 .txclk(clk1), 180 .txdat(dat), 181 .rxclk(clk2), 182 .rxdat(shift2_in) 183 ); 184 185 sync_oneway sync1( 186 .txclk(clk2), 187 .txdat(shift2[0]), 188 .rxclk(clk1), 189 .rxdat(ack) 190 ); 191 192 endmodule