zynq-sandbox

old FPGA projects for ZYNQ
git clone http://frotz.net/git/zynq-sandbox.git
Log | Files | Refs | README

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