OpenCores
URL https://opencores.org/ocsvn/tv80/tv80/trunk

Subversion Repositories tv80

[/] [tv80/] [trunk/] [rtl/] [simple_gmii/] [simple_gmii_core.v] - Blame information for rev 107

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 65 ghutchis
//
2
// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
3
//
4
// Permission is hereby granted, free of charge, to any person obtaining a 
5
// copy of this software and associated documentation files (the "Software"), 
6
// to deal in the Software without restriction, including without limitation 
7
// the rights to use, copy, modify, merge, publish, distribute, sublicense, 
8
// and/or sell copies of the Software, and to permit persons to whom the 
9
// Software is furnished to do so, subject to the following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included 
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
15
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
17
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
18
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
19
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
20
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
 
22
//----------------------------------------------------------------------
23
//  Simple network interface
24
//
25
//  Implements a GMII-like byte-wide interface on one side, and
26
//  an IO-mapped interface to the tv80.
27
 
28
//  IO-interface:
29
//    R0  --  Status register
30
//    R1  --  Control register
31
//    R2  --  RX Length (low)
32
//    R3  --  RX Length (high)
33
//    R4  --  RX Data
34
//    R5  --  TX Data
35
//    R6  --  Configuration
36
 
37
//  Status bits:
38
//    [0]     RX Packet Ready
39
//    [1]     TX Transmit Complete
40
 
41
//  Control bits:
42
//    [0]     Send TX Packet
43
//----------------------------------------------------------------------
44
 
45
module simple_gmii_core
46
  #(parameter txbuf_sz = 512,
47
    parameter rxbuf_sz = 512,
48
    parameter wr_ptr_sz = 10)
49
  (
50
   input      clk,
51
   input      reset,
52
 
53
   // GMII Interface
54
   input [7:0] rx_data,
55
   input       rx_clk,
56
   input       rx_dv,
57
   input       rx_er,
58
 
59
   output reg [7:0] tx_data,
60
   input            tx_clk,
61
   output reg       tx_dv,
62
   output reg       tx_er,
63
 
64
   // RX Buf RAM
65
   output reg         rxbuf_we,
66
   output reg [wr_ptr_sz-1:0] rx_wr_ptr,
67
   output reg [wr_ptr_sz-1:0] rx_rd_ptr,
68
   input [7:0]  rxbuf_data,
69
 
70
   // TX Buf RAM
71
   output reg                 wr_sel_tx_data,
72
   output reg [wr_ptr_sz-1:0] txi_wr_ptr,
73
   //input [7:0]                io_data_in,
74
   output reg [wr_ptr_sz-1:0] txo_xm_ptr,
75
   input  [7:0]               txbuf_data,
76
 
77
   // Register interface
78
   output [1:0]  status_set,
79
   input         start_transmit,   // control[0]
80
   output [15:0] rx_len,
81
   output [7:0]  rx_rd_data,
82
   input         rx_rd_stb,
83
   //input [7:0]   tx_wr_data,
84
   input         tx_wr_stb,
85
   input         en_preamble       // config[0]
86
  );
87
 
88
  //parameter   io_base_addr = 8'hA0;
89
  //parameter txbuf_sz = 512, rxbuf_sz = 512;
90
  //parameter wr_ptr_sz = 10;
91
 
92
  //parameter st_tx_idle = 0, st_tx_xmit = 1;
93
  parameter st_txi_idle = 1'b0, st_txi_xmit = 1'b1;
94
  parameter st_txo_idle = 2'b0, st_txo_pre = 2'b10, st_txo_xmit = 2'b11, st_txo_wait = 2'b01;
95
  parameter st_rxo_idle = 2'b00,
96
            st_rxo_ready = 2'b01,
97
            st_rxo_ack   = 2'b11;
98
 
99
  parameter st_rxin_idle = 2'b00,
100
            st_rxin_pre  = 2'b01,
101
            st_rxin_receive = 2'b11,
102
            st_rxin_hold    = 2'b10;
103
 
104
  parameter SFD = 8'hD5;
105
 
106
  //reg [wr_ptr_sz-1:0] tx_wr_ptr, tx_xm_ptr;
107
  reg [wr_ptr_sz-1:0] rx_count;
108
  reg         txi_state;
109
  reg [1:0]   txo_state;
110
  reg        txi_start;
111
  wire       txo_start;
112
  reg        txo_done;
113
  wire       txi_done;
114
  reg [wr_ptr_sz-1:0] txo_wr_ptr;
115
 
116
 
117
  reg         stat_tx_complete;
118
 
119
  reg         stat_rx_avail;
120
 
121
  reg [1:0]   rxin_state;
122
  reg         rxin_complete;
123
  reg [1:0]   nxt_rxin_state;
124
  reg         nxt_rxin_complete;
125
  reg [wr_ptr_sz-1:0] nxt_rx_wr_ptr;
126
  reg         rd_sel_rx_data;
127
  reg [1:0]   rxo_state;
128
  wire        rxo_complete;
129
  reg         rxo_ack;
130
  wire        rxin_ack;
131
 
132
  //assign      io_select = ((io_base_addr >> 3) == addr[7:3]);
133
 
134
  //------------------------------
135
  // IO Read Mux
136
  //------------------------------
137
 
138
  assign rx_len = { {16-wr_ptr_sz{1'b0}}, rx_count };
139
  assign status_set = { stat_tx_complete, stat_rx_avail };
140
  assign rx_rd_data = rxbuf_data;
141
 
142
  //------------------------------
143
  // Receive Logic
144
  //------------------------------
145
 
146
  always @*
147
    begin
148
      rd_sel_rx_data = rx_rd_stb;
149
      //rxbuf_we = ((rxin_state == st_rxin_idle) | (rxin_state == st_rxin_receive)) & rx_dv;
150
    end
151
  /*
152
  ram_1r_1w #(8, rxbuf_sz, wr_ptr_sz) rxbuf
153
    (.clk     (rx_clk),
154
     .wr_en   (rxbuf_we),
155
     .wr_addr (rx_wr_ptr),
156
     .wr_data (rx_data),
157
 
158
     .rd_addr (rx_rd_ptr),
159
     .rd_data (rxbuf_data));
160
  */
161
 
162
  always @*
163
    begin
164
      rxbuf_we = 0;
165
      nxt_rxin_complete = rxin_complete;
166
      nxt_rxin_state = rxin_state;
167
      nxt_rx_wr_ptr = rx_wr_ptr;
168
 
169
      case (rxin_state)
170
        st_rxin_idle :
171
          begin
172
            if (rx_dv)
173
              begin
174
                nxt_rxin_complete = 0;
175
                if (en_preamble & (rx_data != SFD))
176
                  nxt_rxin_state = st_rxin_pre;
177
                else
178
                  begin
179
                    nxt_rx_wr_ptr = rx_wr_ptr + 1;
180
                    nxt_rxin_state = st_rxin_receive;
181
                    rxbuf_we = 1;
182
                  end
183
              end
184
            else
185
              begin
186
                nxt_rx_wr_ptr = 0;
187
              end
188
          end // case: st_rxin_idle
189
 
190
        st_rxin_pre :
191
          begin
192
            if (rx_data == SFD)
193
              nxt_rxin_state = st_rxin_receive;
194
          end
195
 
196
        st_rxin_receive :
197
          begin
198
            if (rx_dv)
199
              begin
200
                nxt_rx_wr_ptr = rx_wr_ptr + 1;
201
                rxbuf_we = 1;
202
              end
203
            else
204
              begin
205
                nxt_rxin_state = st_rxin_hold;
206
                nxt_rxin_complete = 1;
207
              end
208
          end
209
 
210
        st_rxin_hold :
211
          begin
212
            if (rxin_ack & !rx_dv)
213
              begin
214
                nxt_rxin_state = st_rxin_idle;
215
                nxt_rxin_complete = 0;
216
              end
217
          end
218
 
219
        default :
220
          nxt_rxin_state = st_rxin_idle;
221
      endcase // case(rxin_state)
222
    end // always @ *
223
 
224
  always @(posedge rx_clk)
225
    begin
226
      if (reset)
227
        begin
228
          rxin_state    <= #1 st_rxin_idle;
229
          rxin_complete <= #1 0;
230
          rx_wr_ptr     <= #1 0;
231
        end
232
      else
233
       begin
234
         rxin_state    <= #1 nxt_rxin_state;
235
         rxin_complete <= #1 nxt_rxin_complete;
236
         rx_wr_ptr     <= #1 nxt_rx_wr_ptr;
237
       end // else: !if(reset)
238
    end // always @ (posedge rx_clk)
239
 
240
  /*
241
  always @(posedge rx_clk)
242
    begin
243
      if (reset)
244
        begin
245
          rxin_state    <= #1 st_rxin_idle;
246
          rxin_complete <= #1 0;
247
          rx_wr_ptr     <= #1 0;
248
        end
249
      else
250
        begin
251
          case (rxin_state)
252
            st_rxin_idle :
253
              begin
254
                if (rx_dv)
255
                  begin
256
                    rxin_complete <= #1 0;
257
                    if (en_preamble & (rx_data != SFD))
258
                      rxin_state <= #1 st_rxin_pre;
259
                    else
260
                      begin
261
                        rx_wr_ptr <= #1 rx_wr_ptr + 1;
262
                        rxin_state <= #1 st_rxin_receive;
263
                      end
264
                  end
265
                else
266
                  begin
267
                    rx_wr_ptr <= #1 0;
268
                  end
269
              end // case: st_rxin_idle
270
 
271
            st_rxin_pre :
272
              begin
273
                if (rx_data == SFD)
274
                  rxin_state <= #1 st_rxin_receive;
275
              end
276
 
277
            st_rxin_receive :
278
              begin
279
                if (rx_dv)
280
                  rx_wr_ptr <= #1 rx_wr_ptr + 1;
281
                else
282
                  begin
283
                    rxin_state <= #1 st_rxin_hold;
284
                    rxin_complete <= #1 1;
285
                  end
286
              end
287
 
288
            st_rxin_hold :
289
              begin
290
                if (rxin_ack & !rx_dv)
291
                  begin
292
                    rxin_state <= #1 st_rxin_idle;
293
                    rxin_complete <= #1 0;
294
                  end
295
              end
296
 
297
            default :
298
              rxin_state <= #1 st_rxin_idle;
299
          endcase // case(rxin_state)
300
        end // else: !if(reset)
301
    end // always @ (posedge rx_clk)
302
*/
303
 
304
  sync2 comp_sync (clk, rxin_complete, rxo_complete);
305
  sync2 ack_sync  (rx_clk, rxo_ack, rxin_ack);
306
 
307
  always @(posedge clk)
308
    begin
309
      if (reset)
310
        begin
311
          rx_count <= #1 0;
312
          rxo_state <= #1 st_rxo_idle;
313
          stat_rx_avail <= #1 0;
314
          rxo_ack       <= #1 0;
315
        end
316
      else
317
        begin
318
          case (rxo_state)
319
            st_rxo_idle :
320
              begin
321
                rx_rd_ptr     <= #1 0;
322
                if (rxin_complete)
323
                  begin
324
                    rxo_state <= #1 st_rxo_ready;
325
                    stat_rx_avail <= #1 1;
326
                    rx_count <= #1 rx_wr_ptr;
327
                  end
328
              end
329
 
330
            st_rxo_ready :
331
              begin
332
                if (rd_sel_rx_data)
333
                  rx_rd_ptr <= #1 rx_rd_ptr + 1;
334
 
335
                if (rx_rd_ptr == rx_count)
336
                  begin
337
                    rxo_ack <= #1 1;
338
                    rxo_state <= #1 st_rxo_ack;
339
                    stat_rx_avail <= #1 0;
340
                  end
341
              end // case: st_rxo_ready
342
 
343
            st_rxo_ack :
344
              begin
345
                if (!rxo_complete)
346
                  rxo_state <= #1 st_rxo_idle;
347
              end
348
 
349
            default :
350
              rxo_state <= #1 st_rxo_idle;
351
          endcase // case(rxo_state)
352
        end // else: !if(reset)
353
    end // always @ (posedge clk)
354
 
355
  //------------------------------
356
  // Transmit Logic
357
  //------------------------------
358
 
359
  always @*
360
    begin
361
      wr_sel_tx_data = tx_wr_stb;
362
    end
363
 
364
  /*
365
  ram_1r_1w #(8, txbuf_sz, wr_ptr_sz) txbuf
366
    (.clk     (clk),
367
     .wr_en   (wr_sel_tx_data),
368
     .wr_addr (txi_wr_ptr),
369
     .wr_data (io_data_in),
370
 
371
     .rd_addr (txo_xm_ptr),
372
     .rd_data (txbuf_data));
373
   */
374
 
375
  always @(posedge clk)
376
    begin
377
      if (reset)
378
        begin
379
          txi_state <= #1 st_txi_idle;
380
          txi_start <= #1 0;
381
          txi_wr_ptr <= #1 0;
382
          stat_tx_complete <= #1 0;
383
        end
384
      else
385
        begin
386
          case (txi_state)
387
            st_txi_idle :
388
              begin
389
                stat_tx_complete <= #1 0;
390
                if (start_transmit)
391
                  begin
392
                    txi_state <= #1 st_txi_xmit;
393
                    txi_start <= #1 1;
394
 
395
                  end
396
                else if (wr_sel_tx_data)
397
                  begin
398
                    txi_wr_ptr <= #1 txi_wr_ptr + 1;
399
                  end
400
              end
401
 
402
            st_txi_xmit :
403
              begin
404
                if (txi_done)
405
                  begin
406
                    txi_start <= #1 0;
407
                    txi_state <= #1 st_txi_idle;
408
                    txi_wr_ptr <= #1 0;
409
                    stat_tx_complete <= #1 1;
410
                  end
411
              end
412
 
413
            default :
414
              txi_state <= #1 st_txi_idle;
415
          endcase // case(txi_state)
416
        end
417
    end // always @ (posedge clk)
418
 
419
  sync2 tx_start_sync (tx_clk, txi_start, txo_start);
420
  sync2 tx_done_sync  (clk, txo_done, txi_done);
421
 
422
 
423
  always @(posedge tx_clk)
424
    begin
425
      if (reset)
426
        begin
427
          txo_state <= #1 st_txo_idle;
428
          txo_wr_ptr <= #1 0;
429
          txo_xm_ptr <= #1 0;
430
          tx_data   <= #1 0;
431
          tx_dv     <= #1 0;
432
          tx_er     <= #1 0;
433
          txo_done  <= #1 0;
434
        end
435
      else
436
        begin
437
          case (txo_state)
438
            st_txo_idle :
439
              begin
440
                txo_xm_ptr <= #1 0;
441
                tx_dv     <= #1 0;
442
                tx_er     <= #1 0;
443
 
444
                if (txo_start)
445
                  begin
446
                    if (en_preamble)
447
                      txo_state <= #1 st_txo_pre;
448
                    else
449
                      txo_state <= #1 st_txo_xmit;
450
                    txo_wr_ptr <= #1 txi_wr_ptr;
451
                  end
452
              end
453
 
454
            st_txo_pre :
455
              begin
456
                tx_er     <= #1 0;
457
                tx_dv     <= #1 1;
458
                if (txo_xm_ptr == 7)
459
                  begin
460
                    txo_xm_ptr <= #1 0;
461
                    txo_state  <= #1 st_txo_xmit;
462
                    tx_data    <= #1 8'hd5;
463
                  end
464
                else
465
                  begin
466
                    txo_xm_ptr <= #1 txo_xm_ptr + 1;
467
                    tx_data    <= #1 8'h55;
468
                  end
469
              end
470
 
471
            st_txo_xmit :
472
              begin
473
                if (txo_xm_ptr == txo_wr_ptr)
474
                  begin
475
                    tx_dv     <= #1 0;
476
                    tx_er     <= #1 0;
477
                    txo_state  <= #1 st_txo_wait;
478
                    txo_wr_ptr <= #1 0;
479
                    txo_done   <= #1 1;
480
                  end
481
                else
482
                  begin
483
                    tx_data   <= #1 txbuf_data;
484
                    tx_dv     <= #1 1;
485
                    tx_er     <= #1 0;
486
                    txo_xm_ptr <= #1 txo_xm_ptr + 1;
487
                  end
488
              end // case: st_txo_xmit
489
 
490
            st_txo_wait :
491
              begin
492
                if (!txo_start)
493
                  begin
494
                    txo_done <= #1 0;
495
                    txo_state <= #1 st_txo_idle;
496
                  end
497
              end
498
 
499
            default :
500
              begin
501
                txo_state <= #1 st_txo_idle;
502
              end
503
          endcase // case(tx_state)
504
        end // else: !if(reset)
505
    end // always @ (posedge clk)
506
 
507
endmodule
508
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.