1//
2// Copyright 2011 Ettus Research LLC
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16//
17
18
19// Parameter LE tells us if we are little-endian.
20// Little-endian means send lower 16 bits first.
21// Default is big endian (network order), send upper bits first.
22
23module fifo19_to_fifo36
24  #(parameter LE=0)
25   (input clk, input reset, input clear,
26    input [18:0] f19_datain,
27    input f19_src_rdy_i,
28    output f19_dst_rdy_o,
29
30    output [35:0] f36_dataout,
31    output f36_src_rdy_o,
32    input f36_dst_rdy_i,
33    output [31:0] debug
34    );
35
36   // Shortfifo on input to guarantee no deadlock
37   wire [18:0] 	  f19_data_int;
38   wire 	  f19_src_rdy_int, f19_dst_rdy_int;
39
40   fifo_short #(.WIDTH(19)) head_fifo
41     (.clk(clk),.reset(reset),.clear(clear),
42      .datain(f19_datain), .src_rdy_i(f19_src_rdy_i), .dst_rdy_o(f19_dst_rdy_o),
43      .dataout(f19_data_int), .src_rdy_o(f19_src_rdy_int), .dst_rdy_i(f19_dst_rdy_int),
44      .space(),.occupied() );
45
46   // Actual f19 to f36 which could deadlock if not connected to shortfifos
47   reg 		  f36_sof_int, f36_eof_int;
48   reg [1:0] 	  f36_occ_int;
49   wire [35:0] 	  f36_data_int;
50   wire 	  f36_src_rdy_int, f36_dst_rdy_int;
51
52   reg [1:0] 	  state;
53   reg [15:0] 	  dat0, dat1;
54
55   wire 	  f19_sof_int  = f19_data_int[16];
56   wire 	  f19_eof_int  = f19_data_int[17];
57   wire 	  f19_occ_int  = f19_data_int[18];
58
59   wire 	  xfer_out = f36_src_rdy_int & f36_dst_rdy_int;
60
61   always @(posedge clk)
62     if(f19_src_rdy_int & ((state==0)|xfer_out))
63       f36_sof_int 	<= f19_sof_int;
64
65   always @(posedge clk)
66     if(f19_src_rdy_int & ((state != 2)|xfer_out))
67       f36_eof_int 	<= f19_eof_int;
68
69   always @(posedge clk)
70     if(reset)
71       begin
72	  state 	<= 0;
73	  f36_occ_int <= 0;
74       end
75     else
76       if(f19_src_rdy_int)
77	 case(state)
78	   0 :
79	     begin
80		dat0 <= f19_data_int;
81		if(f19_eof_int)
82		  begin
83		     state <= 2;
84		     f36_occ_int <= f19_occ_int ? 2'b01 : 2'b10;
85		  end
86		else
87		  state <= 1;
88	     end
89	   1 :
90	     begin
91		dat1 <= f19_data_int;
92		state <= 2;
93		if(f19_eof_int)
94		  f36_occ_int <= f19_occ_int ? 2'b11 : 2'b00;
95	     end
96	   2 :
97	     if(xfer_out)
98	       begin
99		  dat0 <= f19_data_int;
100		  if(f19_eof_int) // remain in state 2 if we are at eof
101		    f36_occ_int <= f19_occ_int ? 2'b01 : 2'b10;
102		  else
103		    state 	   <= 1;
104	       end
105	 endcase // case(state)
106       else
107	 if(xfer_out)
108	   begin
109	      state 	   <= 0;
110	      f36_occ_int <= 0;
111	   end
112
113   assign    f19_dst_rdy_int  = xfer_out | (state != 2);
114   assign    f36_data_int     = LE ? {f36_occ_int,f36_eof_int,f36_sof_int,dat1,dat0} :
115				{f36_occ_int,f36_eof_int,f36_sof_int,dat0,dat1};
116   assign    f36_src_rdy_int  = (state == 2);
117
118   assign    debug = state;
119
120   // Shortfifo on output to guarantee no deadlock
121   fifo_short #(.WIDTH(36)) tail_fifo
122     (.clk(clk),.reset(reset),.clear(clear),
123      .datain(f36_data_int), .src_rdy_i(f36_src_rdy_int), .dst_rdy_o(f36_dst_rdy_int),
124      .dataout(f36_dataout), .src_rdy_o(f36_src_rdy_o), .dst_rdy_i(f36_dst_rdy_i),
125      .space(),.occupied() );
126
127endmodule // fifo19_to_fifo36
128