Fix warnings, mostly from implicitly defined wires or unspecified widths
[debian/gnuradio] / usrp2 / fpga / serdes / serdes_tx.v
1
2 // SERDES Interface
3
4 // LS-Byte is sent first, MS-Byte is second
5 // Invalid K Codes
6 //  K0.0  000-00000  Error detected
7 //  K31.7 111-11111  Loss of input signal
8
9 // Valid K Codes
10 //  K28.0 000-11100
11 //  K28.1 001-11100  Alternate COMMA?
12 //  K28.2 010-11100
13 //  K28.3 011-11100
14 //  K28.4 100-11100
15 //  K28.5 101-11100  Standard COMMA?
16 //  K28.6 110-11100
17 //  K28.7 111-11100  Bad COMMA?
18 //  K23.7 111-10111
19 //  K27.7 111-11011
20 //  K29.7 111-11101
21 //  K30.7 111-11110
22
23 module serdes_tx
24   #(parameter FIFOSIZE = 9)
25     (input clk,
26      input rst,
27      
28      // TX HW Interface
29      output ser_tx_clk,
30      output reg [15:0] ser_t,
31      output reg ser_tklsb,
32      output reg ser_tkmsb,
33      
34      // TX Stream Interface
35      input [31:0] rd_dat_i,
36      input [3:0] rd_flags_i,
37      output rd_ready_o,
38      input rd_ready_i,
39
40      // Flow control interface
41      input inhibit_tx,
42      input send_xon,
43      input send_xoff,
44      output sent,
45
46      // FIFO Levels
47      output [15:0] fifo_occupied,
48      output fifo_full,
49      output fifo_empty,
50
51      // DEBUG
52      output [31:0] debug
53      );
54
55    localparam K_COMMA = 8'b101_11100;     // 0xBC K28.5
56    localparam K_IDLE = 8'b001_11100;      // 0x3C K28.1
57    localparam K_PKT_START = 8'b110_11100; // 0xDC K28.6
58    localparam K_PKT_END = 8'b100_11100;   // 0x9C K28.4
59    localparam K_XON = 8'b010_11100;       // 0x5C K28.2
60    localparam K_XOFF = 8'b011_11100;      // 0x7C K28.3
61    localparam K_LOS = 8'b111_11111;       // 0xFF K31.7
62    localparam K_ERROR = 8'b000_00000;     // 0x00 K00.0
63    localparam D_56 = 8'b110_00101;        // 0xC5 D05.6
64    assign     ser_tx_clk = clk;
65    
66    localparam IDLE = 3'd0;
67    localparam RUN1 = 3'd1;
68    localparam RUN2 = 3'd2;
69    localparam DONE = 3'd3;
70    localparam SENDCRC = 3'd4;
71    localparam WAIT = 3'd5;
72    
73    reg [2:0]  state;
74    
75    reg [15:0] CRC;
76    wire [15:0] nextCRC;
77    reg [3:0]   wait_count;
78    
79    // Internal FIFO, size 9 is 2K, size 10 is 4K bytes
80    wire        sop_o, eop_o;
81    wire [31:0] data_o;
82
83    wire        rd_sop_i  = rd_flags_i[0];
84    wire        rd_eop_i  = rd_flags_i[1];
85    wire [1:0]  rd_occ_i = rd_flags_i[3:2];  // Unused
86
87    wire        have_data, empty, read;
88    fifo_cascade #(.WIDTH(34),.SIZE(FIFOSIZE)) serdes_tx_fifo
89      (.clk(clk),.reset(rst),.clear(0),
90       .datain({rd_sop_i,rd_eop_i,rd_dat_i}), .src_rdy_i(rd_ready_i), .dst_rdy_o(rd_ready_o),
91       .dataout({sop_o,eop_o,data_o}), .dst_rdy_i(read), .src_rdy_o(have_data),
92       .space(), .occupied(fifo_occupied) );
93    
94    assign fifo_full   = ~rd_ready_o;
95    assign empty       = ~have_data;
96    assign fifo_empty  = empty;
97    
98    // FIXME Implement flow control   
99    reg [15:0]  second_word;
100    reg [33:0]  pipeline;
101    
102    assign      read = (~send_xon & ~send_xoff & (state==RUN2)) | ((state==IDLE) & ~empty & ~sop_o);
103    assign      sent = send_xon | send_xoff;
104    // 2nd half of above probably not necessary.  Just in case we get junk between packets
105    
106    always @(posedge clk)
107      if(rst)
108        begin
109           state <= IDLE;
110           wait_count <= 0;
111           {ser_tkmsb,ser_tklsb,ser_t} <= 18'd0;
112                         //{2'b10,K_COMMA,K_COMMA};  
113           // make tkmsb and tklsb different so they can go in IOFFs
114        end
115      else
116        if(send_xon)
117          {ser_tkmsb,ser_tklsb,ser_t} <= {2'b11,K_XON,K_XON};
118        else if(send_xoff)
119          {ser_tkmsb,ser_tklsb,ser_t} <= {2'b11,K_XOFF,K_XOFF};
120        else
121          case(state)
122            IDLE :
123              begin
124                 if(sop_o & ~empty & ~inhibit_tx)
125                   begin
126                      {ser_tkmsb,ser_tklsb,ser_t} <= {2'b11,K_PKT_START,K_PKT_START};
127                      state <= RUN1;
128                   end
129                 else
130                   {ser_tkmsb,ser_tklsb,ser_t} <= {2'b10,K_COMMA,D_56};
131              end
132            RUN1 :
133              begin
134                 if(empty | inhibit_tx)
135                   {ser_tkmsb,ser_tklsb,ser_t} <= {2'b10,K_COMMA,D_56};
136                 else
137                   begin
138                      {ser_tkmsb,ser_tklsb,ser_t} <= {2'b00,data_o[15:0]};
139                      state <= RUN2;
140                   end
141              end
142            RUN2 :
143              begin
144                 {ser_tkmsb,ser_tklsb,ser_t} <= {2'b00,data_o[31:16]};
145                 if(eop_o)
146                   state <= DONE;
147                 else
148                   state <= RUN1;
149              end
150            DONE :
151              begin
152                 {ser_tkmsb,ser_tklsb,ser_t} <= {2'b11,K_PKT_END,K_PKT_END};
153                 state <= SENDCRC;
154              end
155            SENDCRC :
156              begin
157                 {ser_tkmsb,ser_tklsb,ser_t} <= {2'b00,CRC};
158                 state <= WAIT;
159                 wait_count <= 4'd15;
160              end
161            WAIT :
162              begin
163                 {ser_tkmsb,ser_tklsb,ser_t} <= {2'b10,K_COMMA,D_56};
164                 if(wait_count == 0)
165                   state <= IDLE;
166                 else
167                   wait_count <= wait_count - 1;
168              end
169            default
170              state <= IDLE;
171          endcase // case(state)
172    
173    always @(posedge clk)
174      if(rst)
175        CRC <= 16'hFFFF;
176      else if(state == IDLE)
177        CRC <= 16'hFFFF;
178      else if( (~empty & ~inhibit_tx & (state==RUN1)) || (state==RUN2) )
179        CRC <= nextCRC;
180    
181    CRC16_D16 crc_blk( (state==RUN1) ? data_o[15:0] : data_o[31:16], CRC, nextCRC);
182
183    assign debug = { 28'd0, state[2:0] };
184    
185 endmodule // serdes_tx
186