// cross clock domain 1 byte fall through FIFO
// Author: Nicolae Dumitrache
// e-mail: ndumitrache@opencores.org

module q1(
	   input wr_clk,
		input wr_en,
		input [7:0]din,
		output full,
		
	   input rd_clk,
		input rd_en,
		output reg [7:0]dout,
		output empty
	);

	reg [1:0]stw = 2'b00;   // wr_clk domain write state
	reg [1:0]str = 2'b00;   // rd_clk domain read state
	reg [1:0]wstr = 2'b00;  // wr clk domain read state
	reg [1:0]rstw = 2'b00;  // rd_clk domain write state
	assign full = stw != 2'b00;
	assign empty = str != 2'b01;
	
	always @(posedge wr_clk) begin
		wstr <= str;
		case(stw)
			2'b00: if(wr_en) {stw, dout} <= {2'b01, din};
			2'b01: if(wstr == 2'b10) stw <= 2'b10;	// full
			default: if(wstr == 2'b00) stw <= 2'b00;
		endcase
	end

	always @(posedge rd_clk) begin
		rstw <= stw;
		case(str)
			2'b00: if(rstw == 2'b01) str <= 2'b01;	
			2'b01: if(rd_en) str <= 2'b10;	  // full
			default: if(rstw == 2'b10) str <= 2'b00; 
		endcase
	end
	
endmodule

/*                 +----------------------+
                   |                      |
                   |  write(stw)          |      read(str)
                   V    +-+               |        +-+ 
               +------>>|0|               +--------|0|<<------+
               |        +-+                        +-+ empty  |
               |         |                          |         |
               |         |write            +------>>|         |
               |         |                 |        |         |
               |         V                 |        V         |
               |        +-+                |       +-+        |
               |   full |1|----------------+       |1|        |
               |        +-+                        +-+        |
               |         |                          |         |
               |         |<<-----+                  |read     |
               |         |       |                  |         |
               |         V       |                  V         |
               |        +-+      |                 +-+        |
               |   full |2|---+  +-----------------|2| empty  |
               |        +-+   |                    +-+        |
               |         |    |                     |         |
               |         |    +------------------->>|         |
               +---------+                          +---------+
*/

