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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [verilog/] [smii_phy.v] - Diff between revs 51 and 403

Only display areas with differences | Details | Blame | View Log

Rev 51 Rev 403
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
////  SMII Receiver/Decoder (usually at PHY end)                  ////
////  SMII Receiver/Decoder (usually at PHY end)                  ////
////                                                              ////
////                                                              ////
////  Description                                                 ////
////  Description                                                 ////
////  Low pin count serial MII ethernet interface                 ////
////  Low pin count serial MII ethernet interface                 ////
////                                                              ////
////                                                              ////
////  To Do:                                                      ////
////  To Do:                                                      ////
////   -                                                          ////
////   -                                                          ////
////                                                              ////
////                                                              ////
////  Author(s):                                                  ////
////  Author(s):                                                  ////
////      - Michael Unneback, unneback@opencores.org              ////
////      - Michael Unneback, unneback@opencores.org              ////
////        ORSoC AB          michael.unneback@orsoc.se           ////
////        ORSoC AB          michael.unneback@orsoc.se           ////
////      - Julius Baxter, jb@orsoc.se                            ////
////      - Julius Baxter, jb@orsoc.se                            ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
////                                                              ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
//// later version.                                               ////
////                                                              ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
//// details.                                                     ////
////                                                              ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
module smii_phy
module smii_phy
  (
  (
   // SMII
   // SMII
    input     smii_tx,
    input     smii_tx,
    input     smii_sync,
    input     smii_sync,
    output reg    smii_rx,
    output reg    smii_rx,
 
 
   // MII
   // MII
   // TX
   // TX
   /* ALL I/Os swapped compared to SMII on MAC end MAC - jb */
   /* ALL I/Os swapped compared to SMII on MAC end MAC - jb */
    output reg [3:0] ethphy_mii_tx_d,
    output reg [3:0] ethphy_mii_tx_d,
    output reg       ethphy_mii_tx_en,
    output reg       ethphy_mii_tx_en,
    output reg       ethphy_mii_tx_err,
    output reg       ethphy_mii_tx_err,
    input            ethphy_mii_tx_clk,
    input            ethphy_mii_tx_clk,
   // RX
   // RX
    input [3:0]      ethphy_mii_rx_d,
    input [3:0]      ethphy_mii_rx_d,
    input            ethphy_mii_rx_dv,
    input            ethphy_mii_rx_dv,
    input            ethphy_mii_rx_err,
    input            ethphy_mii_rx_err,
    input            ethphy_mii_rx_clk,
    input            ethphy_mii_rx_clk,
    input            ethphy_mii_mcoll,
    input            ethphy_mii_mcoll,
    input            ethphy_mii_crs,
    input            ethphy_mii_crs,
 
 
    input            fast_ethernet,
    input            fast_ethernet,
    input            duplex,
    input            duplex,
    input            link,
    input            link,
 
 
   // internal
   // internal
    //input [10:1] state,
    //input [10:1] state,
   // clock and reset
   // clock and reset
    input        clk, /* Global reference clock for both SMII modules */
    input        clk, /* Global reference clock for both SMII modules */
    input        rst_n
    input        rst_n
   );
   );
 
 
   reg [3:0]      rx_tmp;
   reg [3:0]      rx_tmp;
 
 
   reg           jabber = 0;
   reg           jabber = 0;
 
 
   reg           mtx_clk_tmp, mrx_clk_tmp;
   reg           mtx_clk_tmp, mrx_clk_tmp;
 
 
   reg [3:0]      tx_cnt;
   reg [3:0]      tx_cnt;
   reg [3:0]      rx_cnt;
   reg [3:0]      rx_cnt;
 
 
 
 
/**************************************************************************/
/**************************************************************************/
/* Counters */
/* Counters */
/**************************************************************************/
/**************************************************************************/
 
 
   /* Generate the state counter, based on incoming sync signal */
   /* Generate the state counter, based on incoming sync signal */
   /* 10-bit shift register, indicating where we are */
   /* 10-bit shift register, indicating where we are */
   reg [10:1]    state_shiftreg;
   reg [10:1]    state_shiftreg;
 
 
   /* A wire hooked up from bit 0 with the last byte of the state counter/shiftreg */
   /* A wire hooked up from bit 0 with the last byte of the state counter/shiftreg */
   wire [7:0] state_shiftreg_top_byte;
   wire [7:0] state_shiftreg_top_byte;
   assign state_shiftreg_top_byte[7:0] = state_shiftreg[10:3];
   assign state_shiftreg_top_byte[7:0] = state_shiftreg[10:3];
 
 
   always @(posedge clk)
   always @(posedge clk)
     begin
     begin
        if (!rst_n)
 
          begin
 
             state_shiftreg <= 10'b0000000001;
 
          end
 
        else
 
          begin
 
             if (smii_sync) /* sync signal from MAC */
             if (smii_sync) /* sync signal from MAC */
               state_shiftreg <= 10'b0000000010;
          state_shiftreg <= 10'b0000000010;
             else if (state_shiftreg[10])
        else if (state_shiftreg[10])
               state_shiftreg <= 10'b0000000001;
          state_shiftreg <= 10'b0000000001;
             else
        else
               state_shiftreg[10:2] <= state_shiftreg[9:1];
               state_shiftreg[10:2] <= state_shiftreg[9:1];
          end // else: !if(!rst_n)      
     end
     end // always @ (posedge clk)
 
 
 
 
 
   /* counter from 0 to 9, counting the 10-bit segments we'll transmit
   /* counter from 0 to 9, counting the 10-bit segments we'll transmit
    via SMII*/
    via SMII*/
   reg [3:0] segment_ctr;
   reg [3:0] segment_ctr;
 
 
   always @(posedge clk)
   always @(posedge clk)
     begin
     begin
        if(!rst_n)
        if(!rst_n)
          segment_ctr <= 4'h0;
          segment_ctr <= 4'h0;
        else
        else
          begin
          begin
             if(fast_ethernet) /* If using 100Mbs, then each segment is
             if(fast_ethernet) /* If using 100Mbs, then each segment is
                            different, we don't count the repeats */
                            different, we don't count the repeats */
               segment_ctr <= 4'h0;
               segment_ctr <= 4'h0;
             else if (state_shiftreg[10])
             else if (state_shiftreg[10])
               if (segment_ctr == 4'h9) /* Wrap */
               if (segment_ctr == 4'h9) /* Wrap */
                 segment_ctr <= 4'h0;
                 segment_ctr <= 4'h0;
               else /* Increment */
               else /* Increment */
                 segment_ctr <= segment_ctr + 1'b1;
                 segment_ctr <= segment_ctr + 1'b1;
          end
          end
     end // always @ (posedge clk)
     end // always @ (posedge clk)
 
 
 
 
/**************************************************************************/
/**************************************************************************/
/* RX path logic PHY->(MII->SMII)->MAC */
/* RX path logic PHY->(MII->SMII)->MAC */
/**************************************************************************/
/**************************************************************************/
 
 
   reg rx_nibble_sel, rx_byte_valid;
 
   reg [7:0] rx_data_byte_rx_clk;
   reg [7:0] rx_data_byte_rx_clk;
 
 
   reg [4:0] rx_dv_nib_0;
   reg [4:0] rx_dv_nib_0;
   reg       rx_nib_first,rx_nib_first_r;  // if high, nib_0 contains the "first" of the pair of nibs
   reg       rx_nib_first,rx_nib_first_r;  // if high, nib_0 contains the "first" of the pair of nibs
   reg [3:0] rx_segment_begin_num;
   reg [3:0] rx_segment_begin_num;
 
 
   // Allow us to check if RX DV has been low for a while
   // Allow us to check if RX DV has been low for a while
   reg [3:0] rx_dv_long_low_sr;
   reg [3:0] rx_dv_long_low_sr;
   wire      rx_dv_long_low;
   wire      dv_long_low;
   always @(posedge ethphy_mii_rx_clk)
   always @(posedge ethphy_mii_rx_clk)
     rx_dv_long_low_sr[3:0] <= {rx_dv_long_low_sr[2:0], ethphy_mii_rx_dv};
     rx_dv_long_low_sr[3:0] <= {rx_dv_long_low_sr[2:0], ethphy_mii_rx_dv};
   assign rx_dv_long_low = ~(|rx_dv_long_low_sr[3:0]);
   assign rx_dv_long_low = ~(|rx_dv_long_low_sr);
   reg      rx_dv;
   wire [9:0] rx_fifo_out;
   wire [8:0] rx_fifo_out;
 
   wire       rx_fifo_empty,rx_fifo_almost_empty;
   wire       rx_fifo_empty,rx_fifo_almost_empty;
   reg        rx_fifo_pop;
 
 
 
   always @(posedge ethphy_mii_rx_clk or negedge rst_n)
   always @(posedge ethphy_mii_rx_clk or negedge rst_n)
     begin
     begin
        if(!rst_n)
        if(!rst_n)
          begin
          begin
             rx_dv_nib_0 <= 0;
             rx_dv_nib_0 <= 0;
             rx_nib_first <= 0;
             rx_nib_first <= 0;
             rx_nib_first_r <= 0;
             rx_nib_first_r <= 0;
          end
          end
        else
        else
          begin
          begin
             if (!rx_nib_first)
             if (!rx_nib_first)
               rx_dv_nib_0 <= {ethphy_mii_rx_dv,ethphy_mii_rx_d};
               rx_dv_nib_0 <= {ethphy_mii_rx_dv,ethphy_mii_rx_d};
             if(ethphy_mii_rx_dv)
             if(ethphy_mii_rx_dv)
               rx_nib_first <= ~rx_nib_first;
               rx_nib_first <= ~rx_nib_first;
 
 
             rx_nib_first_r <= rx_nib_first;
             rx_nib_first_r <= rx_nib_first;
 
 
          end
          end
     end // always @ (posedge ethphy_mii_rx_clk or negedge rst_n)
     end // always @ (posedge ethphy_mii_rx_clk or negedge rst_n)
 
 
     always @(posedge clk or negedge rst_n)
   wire rx_fifo_pop;
       begin
 
          if (!rst_n) rx_fifo_pop <= 0;
 
          else rx_fifo_pop <= (rx_fifo_almost_empty) ? (rx_fifo_pop ? ~rx_fifo_empty : rx_fifo_pop) : 1;
 
 
 
          rx_dv <= (state_shiftreg[10] & (((rx_segment_begin_num == (segment_ctr-1)) && !fast_ethernet)| fast_ethernet)) ? (rx_fifo_pop) : rx_dv;
 
       end
   reg ethphy_mii_rx_dv_r;
 
   wire ethphy_mii_rx_dv_re;
 
   wire ethphy_mii_rx_dv_fe;
 
 
 
   always @(posedge ethphy_mii_rx_clk)
 
        ethphy_mii_rx_dv_r <= ethphy_mii_rx_dv;
 
 
 
   assign ethphy_mii_rx_dv_re = ethphy_mii_rx_dv & !ethphy_mii_rx_dv_r;
 
   assign ethphy_mii_rx_dv_fe = !ethphy_mii_rx_dv & ethphy_mii_rx_dv_r;
 
 
 
   reg  rx_fifo_final_pop;
 
 
   always @(posedge clk)
   always @(posedge clk)
     begin
     if (!rst_n)
        /* remember which counter value we were at when rx enable/valid
       rx_fifo_final_pop <= 0;
         went high.
     else if (rx_fifo_final_pop & state_shiftreg[1] &
         This is only useful when not doing fast ethernet*/
              (((rx_segment_begin_num == segment_ctr) & !fast_ethernet) | fast_ethernet))
 
       rx_fifo_final_pop <= 0;
 
     else if (rx_fifo_pop & rx_fifo_empty)
 
       rx_fifo_final_pop <= 1;
 
 
        /* rx en has gone high - remember the sequence number we're in */
   always @(posedge ethphy_mii_rx_clk)
        if ((rx_segment_begin_num == 4'hf) & (~rx_dv_long_low))
        if (ethphy_mii_rx_dv_re)
          rx_segment_begin_num <= segment_ctr;
          rx_segment_begin_num <= segment_ctr;
 
 
        /* If rx enable goes low again, reset the segment number */
   reg do_fifo_pop;
        if (rx_dv_long_low)
   always @(posedge clk)
             /* reset to 0xf */
     if (!rst_n)
             rx_segment_begin_num <= 4'hf;
       do_fifo_pop <= 0;
     end
     else if (rx_fifo_empty)
 
       do_fifo_pop <= 0;
 
     else if (!rx_fifo_almost_empty)
 
       do_fifo_pop <= 1;
 
 
 
   assign rx_fifo_pop = (state_shiftreg[9] & do_fifo_pop) &
 
                        (((rx_segment_begin_num == segment_ctr) & !fast_ethernet)
 
                         | fast_ethernet);
 
 
 
   reg rx_dv_r;
 
   wire rx_dv;
 
 
 
   // Error where rx_dv goes high one cycle too late, so is low for very first data frame - FIXME!
 
   //reg rx_dv;
 
   always @(posedge clk)
 
     if (!rst_n)
 
       rx_dv_r <= 0;
 
     else if (rx_fifo_final_pop & state_shiftreg[1] &
 
              (((rx_segment_begin_num == segment_ctr) & !fast_ethernet) | fast_ethernet))
 
       rx_dv_r <= 0;
 
     else if (rx_fifo_pop)
 
       rx_dv_r <= rx_fifo_out[9];
 
 
 
   assign rx_dv = rx_dv_r | rx_fifo_pop;
 
 
 
 
 
   reg sending_segment;
 
   always @(posedge clk)
 
     if (!rst_n)
 
       sending_segment <= 0;
 
     else if (rx_fifo_final_pop & state_shiftreg[1] & (((rx_segment_begin_num == segment_ctr) & !fast_ethernet) | fast_ethernet))
 
       sending_segment <= 0;
 
     else if ((state_shiftreg[9] & do_fifo_pop) & (((rx_segment_begin_num == segment_ctr) & !fast_ethernet) | fast_ethernet))
 
       sending_segment <= !rx_fifo_empty;
 
 
     /* A fifo, storing RX bytes coming from the PHY interface */
     /* A fifo, storing RX bytes coming from the PHY interface */
   generic_fifo #(9, 64) rx_fifo
   generic_fifo #(10, 1024, 10) rx_fifo
     (
     (
      // Outputs
      // Outputs
      .psh_full                         (),
      .psh_full                         (),
      .pop_q                            (rx_fifo_out),
      .pop_q                            (rx_fifo_out),
      .pop_empty                        (rx_fifo_empty),
      .pop_empty                        (rx_fifo_empty),
      .almost_empty                     (rx_fifo_almost_empty),
      .almost_empty                     (rx_fifo_almost_empty),
      // Inputs
      // Inputs
      .async_rst_n                      (rst_n),
      .async_rst_n                      (rst_n),
      .psh_clk                          (ethphy_mii_rx_clk),
      .psh_clk                          (ethphy_mii_rx_clk),
      .psh_we                           (rx_nib_first_r),
      .psh_we                           (rx_nib_first_r),
      .psh_d                            ({ethphy_mii_rx_err,ethphy_mii_rx_d,rx_dv_nib_0[3:0]}),
      .psh_d                            ({ethphy_mii_rx_dv,ethphy_mii_rx_err,ethphy_mii_rx_d,rx_dv_nib_0[3:0]}),
      .pop_clk                          (clk),
      .pop_clk                          (clk),
      .pop_re                           ((state_shiftreg[1] & rx_fifo_pop)&(((rx_segment_begin_num == segment_ctr) && !fast_ethernet)| fast_ethernet)));
      .pop_re                           (rx_fifo_pop)
 
      );
 
 
  `ifdef RX_SYNC_1
   reg [9:0] smii_rx_frame_next;
 
   always @(posedge clk)
 
     if (state_shiftreg[10])
 
       smii_rx_frame_next <= rx_dv ? {rx_fifo_out[7:0],1'b1,ethphy_mii_crs} :
 
                             {3'b101,jabber,link,duplex,fast_ethernet,
 
                              ethphy_mii_rx_err,1'b0,ethphy_mii_crs};
 
 
    /* Assign the rx line out */
 
   always @(posedge clk)
   always @(posedge clk)
    smii_rx <= state_shiftreg[1] ? ethphy_mii_crs : /* 1st bit is MII CRS */
     smii_rx <= state_shiftreg[10] &  smii_rx_frame_next[0] |
                    state_shiftreg[2] ? ((rx_dv & (segment_ctr==4'h0) & !fast_ethernet) |
                state_shiftreg[1] &  smii_rx_frame_next[1] |
                                         rx_dv) :
                state_shiftreg[2] &  smii_rx_frame_next[2] |
               // inter-frame status byte or data byte
                state_shiftreg[3] &  smii_rx_frame_next[3] |
               state_shiftreg[3] ? (rx_dv ?  (rx_fifo_out[0]) : ethphy_mii_rx_err) :
                state_shiftreg[4] &  smii_rx_frame_next[4] |
               state_shiftreg[4] ? (rx_dv ?  (rx_fifo_out[1]) : fast_ethernet) :
                state_shiftreg[5] &  smii_rx_frame_next[5] |
               state_shiftreg[5] ? (rx_dv ?  (rx_fifo_out[2]) : duplex) :
                state_shiftreg[6] &  smii_rx_frame_next[6] |
               state_shiftreg[6] ? (rx_dv ?  (rx_fifo_out[3]) : link) :
                state_shiftreg[7] &  smii_rx_frame_next[7] |
               state_shiftreg[7] ? (rx_dv ?  (rx_fifo_out[4]) : jabber) :
                state_shiftreg[8] &  smii_rx_frame_next[8] |
               state_shiftreg[8] ? (rx_dv ?  (rx_fifo_out[5]) : 1) :
                state_shiftreg[9] &  smii_rx_frame_next[9];
               state_shiftreg[9] ? (rx_dv ?  (rx_fifo_out[6]) : 0) :
 
               state_shiftreg[10] ? (rx_dv ?  (rx_fifo_out[7]) : 1) : 0;
 
 
 
  `else // !`ifdef RX_SYNC_1
 
 
 
       /* Assign the rx line out */
 
   always @(posedge clk)
   reg [79:0] rx_statename;
    smii_rx <= state_shiftreg[10] ? ethphy_mii_crs : /* 1st bit is MII CRS */
  always @* begin
                    state_shiftreg[1] ? ((rx_dv & (segment_ctr==4'h0) & !fast_ethernet) |
    case (1)
                                         rx_dv) :
      state_shiftreg[1]   :
               // inter-frame status byte or data byte
        rx_statename = "CRS";
               state_shiftreg[2] ? (rx_dv ?  (rx_fifo_out[0]) : ethphy_mii_rx_err) :
      state_shiftreg[2] :
               state_shiftreg[3] ? (rx_dv ?  (rx_fifo_out[1]) : fast_ethernet) :
        rx_statename = "RX_DV";
               state_shiftreg[4] ? (rx_dv ?  (rx_fifo_out[2]) : duplex) :
      state_shiftreg[3]:
               state_shiftreg[5] ? (rx_dv ?  (rx_fifo_out[3]) : link) :
        rx_statename = "RXD0/RXERR";
               state_shiftreg[6] ? (rx_dv ?  (rx_fifo_out[4]) : jabber) :
      state_shiftreg[4]:
               state_shiftreg[7] ? (rx_dv ?  (rx_fifo_out[5]) : 1) :
        rx_statename = "RXD1/Fast";
               state_shiftreg[8] ? (rx_dv ?  (rx_fifo_out[6]) : 0) :
      state_shiftreg[5]:
               state_shiftreg[9] ? (rx_dv ?  (rx_fifo_out[7]) : 1) : 0;
        rx_statename = "RXD2/Dupl";
  `endif // !`ifdef RX_SYNC_1
      state_shiftreg[6]:
 
        rx_statename = "RXD3/Link";
 
      state_shiftreg[7]:
 
        rx_statename = "RXD4/Jabb";
 
      state_shiftreg[8]:
 
        rx_statename = "RXD5/UNV";
 
      state_shiftreg[9]:
 
        rx_statename = "RXD6/FCD";
 
      state_shiftreg[10] :
 
        rx_statename = "RXD7/AS1";
 
      default:
 
        rx_statename = "XXXXXXX";
 
    endcase // case (1)
 
  end // always @ *
 
 
 
 
 
 
   /* Status seq.: CRS, DV, ER, Speed, Duplex, Link, Jabber, UPV, FCD, 1 */
   /* Status seq.: CRS, DV, ER, Speed, Duplex, Link, Jabber, UPV, FCD, 1 */
   //    {1'b1,1'b0,1'b1,jabber,link,duplex,,ethphy_mii_rx_err});
   //    {1'b1,1'b0,1'b1,jabber,link,duplex,,ethphy_mii_rx_err});
 
 
 
 
/**************************************************************************/
/**************************************************************************/
/* TX path logic MAC->(SMII->MII)->PHY */
/* TX path logic MAC->(SMII->MII)->PHY */
/**************************************************************************/
/**************************************************************************/
 
 
   /* We ignore the data when TX_EN bit is not high -
   /* We ignore the data when TX_EN bit is not high -
    it's only used in MAC to MAC comms*/
    it's only used in MAC to MAC comms*/
 
 
 
 
   /* Register the sequence appropriately as it comes in */
   /* Register the sequence appropriately as it comes in */
   reg tx_er_seqbit_scratch;
   reg tx_er_seqbit_scratch;
   reg tx_en_seqbit_scratch;
   reg tx_en_seqbit_scratch;
   reg [7:0] tx_data_byte_scratch;
   reg [7:0] tx_data_byte_scratch;
 
 
   reg [2:0] tx_byte_to_phy; /* PHY sourced TX_CLK domain */
   reg [2:0] tx_byte_to_phy; /* PHY sourced TX_CLK domain */
 
 
   wire      tx_fifo_empty, tx_fifo_almost_empty;
   wire      tx_fifo_empty, tx_fifo_almost_empty;
   wire      tx_fifo_full;
   wire      tx_fifo_full;
   wire [7:0] tx_fifo_q_dat;
   wire [7:0] tx_fifo_q_dat;
   wire       tx_fifo_q_err;
   wire       tx_fifo_q_err;
   reg        tx_fifo_pop;
   reg        tx_fifo_pop;
   reg [3:0]  tx_segment_begin_num;
   reg [3:0]  tx_segment_begin_num;
   wire [3:0] tx_segment_load_num;
   wire [3:0] tx_segment_load_num;
 
 
   assign tx_segment_load_num = (tx_segment_begin_num == 0) ? 4'h9 : tx_segment_begin_num - 1;
   assign tx_segment_load_num = (tx_segment_begin_num == 0) ? 4'h9 : tx_segment_begin_num - 1;
 
 
   /* Signal to tell us an appropriate time to copy the values out of the
   /* Signal to tell us an appropriate time to copy the values out of the
    temp regs we put the incoming TX line into when we've received a
    temp regs we put the incoming TX line into when we've received a
    sequence off the SMII TX line that has TX_EN high */
    sequence off the SMII TX line that has TX_EN high */
   wire      tx_seqbits_copy;
   wire      tx_seqbits_copy;
   assign tx_seqbits_copy = (
   assign tx_seqbits_copy = (
                             (
                             (
                              ((!fast_ethernet) & (segment_ctr == tx_segment_load_num)) |
                              ((!fast_ethernet) & (segment_ctr == tx_segment_load_num)) |
                              fast_ethernet
                              fast_ethernet
                             )
                             )
                             & tx_en_seqbit_scratch & state_shiftreg[1]
                             & tx_en_seqbit_scratch & state_shiftreg[1]
                            );
                            );
 
 
   always @(posedge clk)
   always @(posedge clk)
     begin
     begin
        /* remember which counter value we were at when tx enable/valid
        /* remember which counter value we were at when tx enable/valid
         went high.
         went high.
         This is only useful when not doing fast ethernet*/
         This is only useful when not doing fast ethernet*/
 
 
        /* tx en has gone high - remember the sequence number we're in */
        /* tx en has gone high - remember the sequence number we're in */
        if ((tx_segment_begin_num == 4'hf) & (tx_en_seqbit_scratch))
        if ((tx_segment_begin_num == 4'hf) & (tx_en_seqbit_scratch))
          tx_segment_begin_num <= segment_ctr;
          tx_segment_begin_num <= segment_ctr;
 
 
        /* If tx enable goes low again, reset the segment number */
        /* If tx enable goes low again, reset the segment number */
        if (!tx_en_seqbit_scratch)
        if (!tx_en_seqbit_scratch)
             /* reset to 0xf */
             /* reset to 0xf */
             tx_segment_begin_num <= 4'hf;
             tx_segment_begin_num <= 4'hf;
     end
     end
 
 
 
 
   always @(posedge clk)
   always @(posedge clk)
     begin
     begin
        if (!rst_n)
        if (!rst_n)
          begin
          begin
             tx_er_seqbit_scratch <= 0;
             tx_er_seqbit_scratch <= 0;
             tx_en_seqbit_scratch <= 0;
             tx_en_seqbit_scratch <= 0;
             tx_data_byte_scratch <= 0;
             tx_data_byte_scratch <= 0;
          end
          end
        else
        else
          begin
          begin
             if(state_shiftreg[1])
             if(state_shiftreg[1])
               tx_er_seqbit_scratch <= smii_tx;
               tx_er_seqbit_scratch <= smii_tx;
 
 
             if(state_shiftreg[2])
             if(state_shiftreg[2])
               tx_en_seqbit_scratch <= smii_tx;
               tx_en_seqbit_scratch <= smii_tx;
 
 
             /* Preserve all but current bit of interest, as indicated
             /* Preserve all but current bit of interest, as indicated
              by state vector bit (reversed, becuase we get MSbit
              by state vector bit (reversed, becuase we get MSbit
              first) and OR in the current smii_tx line value at this
              first) and OR in the current smii_tx line value at this
              position*/
              position*/
             if((|state_shiftreg[10:3]) & tx_en_seqbit_scratch)
             if((|state_shiftreg[10:3]) & tx_en_seqbit_scratch)
               tx_data_byte_scratch <= (tx_data_byte_scratch & ~state_shiftreg_top_byte) |
               tx_data_byte_scratch <= (tx_data_byte_scratch & ~state_shiftreg_top_byte) |
                                       ({8{smii_tx}} & state_shiftreg_top_byte);
                                       ({8{smii_tx}} & state_shiftreg_top_byte);
 
 
          end
          end
     end // always @ (posedge clk)
     end // always @ (posedge clk)
 
 
   reg [3:0] nib;
   reg [3:0] nib;
 
 
 
 
 
 
   /* In the event we have a valid byte frame then get it to the
   /* In the event we have a valid byte frame then get it to the
    PHY as quickly as possible - this is TX_CLK domain */
    PHY as quickly as possible - this is TX_CLK domain */
   always @(posedge ethphy_mii_tx_clk or negedge rst_n)
   always @(posedge ethphy_mii_tx_clk or negedge rst_n)
     begin
     begin
        if(!rst_n)
        if(!rst_n)
          begin
          begin
             tx_byte_to_phy <= 0;
             tx_byte_to_phy <= 0;
             tx_fifo_pop <= 1'b0;
             tx_fifo_pop <= 1'b0;
             /* Output MII registers to the PHY */
             /* Output MII registers to the PHY */
             ethphy_mii_tx_d <= 0;
             ethphy_mii_tx_d <= 0;
             ethphy_mii_tx_en <= 0;
             ethphy_mii_tx_en <= 0;
             ethphy_mii_tx_err <= 0;
             ethphy_mii_tx_err <= 0;
 
 
          end
          end
        else
        else
          begin
          begin
             /* If fast_ethernet/100mbs we wait until the FIFO is full
             /* If fast_ethernet/100mbs we wait until the FIFO is full
              otherwise, we push out the byte each time we get one */
              otherwise, we push out the byte each time we get one */
             //if((!tx_fifo_empty && !fast_ethernet) ||
             //if((!tx_fifo_empty && !fast_ethernet) ||
             //(tx_fifo_full && fast_ethernet))
             //(tx_fifo_full && fast_ethernet))
             if (!tx_fifo_almost_empty)
             if (!tx_fifo_almost_empty)
               begin
               begin
                  if(tx_byte_to_phy == 0)
                  if(tx_byte_to_phy == 0)
                    begin
                    begin
                       tx_byte_to_phy <= 1;
                       tx_byte_to_phy <= 1;
                       tx_fifo_pop <= 1;
                       tx_fifo_pop <= 1;
                    end
                    end
               end
               end
 
 
             /* FIFO control loop */
             /* FIFO control loop */
             if (tx_byte_to_phy == 1)/* Output bits 3-0 (bottom nibble ) */
             if (tx_byte_to_phy == 1)/* Output bits 3-0 (bottom nibble ) */
               begin
               begin
 
 
                  ethphy_mii_tx_en <= 1;
                  ethphy_mii_tx_en <= 1;
 
 
                  tx_fifo_pop <= 0;
                  tx_fifo_pop <= 0;
 
 
                  tx_byte_to_phy <= 2;
                  tx_byte_to_phy <= 2;
 
 
                  ethphy_mii_tx_d <= tx_fifo_q_dat[3:0];
                  ethphy_mii_tx_d <= tx_fifo_q_dat[3:0];
                  nib <= tx_fifo_q_dat[7:4];
                  nib <= tx_fifo_q_dat[7:4];
                  ethphy_mii_tx_err <= tx_fifo_q_err;
                  ethphy_mii_tx_err <= tx_fifo_q_err;
 
 
               end
               end
             else if (tx_byte_to_phy == 2) /* Output bits 7-4 (top nibble) */
             else if (tx_byte_to_phy == 2) /* Output bits 7-4 (top nibble) */
               begin
               begin
                  //ethphy_mii_tx_d <= tx_fifo_q_dat[7:4];
                  //ethphy_mii_tx_d <= tx_fifo_q_dat[7:4];
 
 
                  ethphy_mii_tx_d <= nib;
                  ethphy_mii_tx_d <= nib;
 
 
                  if(!tx_fifo_empty) /* Check if more in FIFO */
                  if(!tx_fifo_empty) /* Check if more in FIFO */
                    begin
                    begin
                       tx_fifo_pop <= 1;
                       tx_fifo_pop <= 1;
                       tx_byte_to_phy <= 1;
                       tx_byte_to_phy <= 1;
                    end
                    end
                  else /* Finish up */
                  else /* Finish up */
                    begin
                    begin
                       tx_byte_to_phy <= 3;
                       tx_byte_to_phy <= 3;
                       ethphy_mii_tx_en <= 0;
 
                    end
                    end
               end
               end
             else if (tx_byte_to_phy == 3) /* De-assert TX_EN */
             else if (tx_byte_to_phy == 3) /* De-assert TX_EN */
               begin
               begin
                  tx_byte_to_phy <= 2'b00;
                  tx_byte_to_phy <= 2'b00;
 
                  ethphy_mii_tx_en <= 0;
               end
               end
          end // else: !if(!rst_n)
          end // else: !if(!rst_n)
     end // always @ (posedge ethphy_mii_tx_clk or negedge rst_n)
     end // always @ (posedge ethphy_mii_tx_clk or negedge rst_n)
 
 
   /* A fifo, storing TX bytes coming from the SMII interface */
   /* A fifo, storing TX bytes coming from the SMII interface */
   generic_fifo #(9, 64) tx_fifo
   generic_fifo #(9, 64, 6) tx_fifo
     (
     (
      // Outputs
      // Outputs
      .psh_full                         (tx_fifo_full),
      .psh_full                         (tx_fifo_full),
      .pop_q                            ({tx_fifo_q_err,tx_fifo_q_dat}),
      .pop_q                            ({tx_fifo_q_err,tx_fifo_q_dat}),
      .pop_empty                        (tx_fifo_empty),
      .pop_empty                        (tx_fifo_empty),
      .almost_empty                     (tx_fifo_almost_empty),
      .almost_empty                     (tx_fifo_almost_empty),
      // Inputs
      // Inputs
      .async_rst_n                      (rst_n),
      .async_rst_n                      (rst_n),
      .psh_clk                          (clk),
      .psh_clk                          (clk),
      .psh_we                           (tx_seqbits_copy),
      .psh_we                           (tx_seqbits_copy),
      .psh_d                            ({tx_er_seqbit_scratch,tx_data_byte_scratch}),
      .psh_d                            ({tx_er_seqbit_scratch,tx_data_byte_scratch}),
      .pop_clk                          (ethphy_mii_tx_clk),
      .pop_clk                          (ethphy_mii_tx_clk),
      .pop_re                           (tx_fifo_pop));
      .pop_re                           (tx_fifo_pop));
 
 
 
 
   //assign mcoll = mcrs & mtxen;
   //assign mcoll = mcrs & mtxen;
 
 
endmodule // smii_top
endmodule // smii_top
 
 
 
 
 
 
/* Generic fifo - this is bad, should probably be done some other way */
/* Generic fifo - this is bad, should probably be done some other way */
module generic_fifo (async_rst_n, psh_clk, psh_we, psh_d, psh_full, pop_clk, pop_re, pop_q, pop_empty, almost_empty);
module generic_fifo (async_rst_n, psh_clk, psh_we, psh_d, psh_full, pop_clk, pop_re, pop_q, pop_empty, almost_empty);
 
 
   parameter dw = 8;
   parameter dw = 8;
   parameter size = 16;
   parameter size = 16;
   parameter size_log_2 = 4;
   parameter size_log_2 = 4;
 
 
   /* Asynch. reset, active low */
   /* Asynch. reset, active low */
   input async_rst_n;
   input async_rst_n;
 
 
   /* Push side signals */
   /* Push side signals */
   input psh_clk;
   input psh_clk;
   input psh_we;
   input psh_we;
   input [dw-1:0] psh_d;
   input [dw-1:0] psh_d;
   output         psh_full;
   output         psh_full;
 
 
   /* Pop side signals */
   /* Pop side signals */
   input          pop_clk;
   input          pop_clk;
   input          pop_re;
   input          pop_re;
   //output reg [dw-1:0] pop_q;
   //output reg [dw-1:0] pop_q;
   output reg [dw-1:0] pop_q;
   output reg [dw-1:0] pop_q;
   output              pop_empty;
   output              pop_empty;
   output wire         almost_empty;
   output wire         almost_empty;
 
 
 
   integer     i;
 
 
   /* Actual FIFO memory */
   /* Actual FIFO memory */
   reg [dw-1:0]   fifo_mem [0:size-1];
   reg [dw-1:0]   fifo_mem [0:size-1];
 
 
 
   initial
 
     begin
 
        for (i=0;i<size;i=i+1)
 
          begin
 
             fifo_mem[i] = {dw{1'b0}};
 
          end
 
     end
 
 
 
 
   /* FIFO position ptr regs */
   /* FIFO position ptr regs */
   reg [size_log_2 - 1 : 0 ]   wr_ptr, rd_ptr, ctr;
   reg [size_log_2 - 1 : 0 ]   wr_ptr, rd_ptr, ctr;
 
 
   integer     i;
 
 
 
 
 
   /* FIFO full signal for push side */
   /* FIFO full signal for push side */
   //assign psh_full = (ptr == size-1) ? 1 : 0;
   //assign psh_full = (ptr == size-1) ? 1 : 0;
   /* This full logic means we all but one slot in the FIFO */
   /* This full logic means we all but one slot in the FIFO */
   assign psh_full = ctr == size;
   assign psh_full = ctr == size;
 
 
   /* FIFO empty signal for pop side */
   /* FIFO empty signal for pop side */
   //assign pop_empty = (ptr == 0) ? 1 : 0;
   //assign pop_empty = (ptr == 0) ? 1 : 0;
   //assign pop_empty = ctr==0;
   //assign pop_empty = ctr==0;
   assign pop_empty = rd_ptr == wr_ptr;
   assign pop_empty = rd_ptr == wr_ptr;
 
 
   assign almost_empty = ctr < 2;
   assign almost_empty = ctr < 16;
 
 
   always @(posedge pop_re or negedge async_rst_n)
   always @(posedge pop_re or negedge async_rst_n)
     begin
     begin
        if (!async_rst_n)
        if (!async_rst_n)
 
          begin
          rd_ptr <= 0;
          rd_ptr <= 0;
 
             pop_q <= 0;
 
          end
        else
        else
          begin
          begin
             pop_q = fifo_mem[rd_ptr];
             if (!pop_empty)
             rd_ptr <= rd_ptr + 1;
               begin
 
                  pop_q <= fifo_mem[rd_ptr];
             ctr <= ctr - 1;
             ctr <= ctr - 1;
 
                  rd_ptr <= rd_ptr + 1;
 
               end
 
 
          end
          end
     end
     end
 
 
   always @(posedge psh_we or negedge async_rst_n)
   always @(posedge psh_we or negedge async_rst_n)
     begin
     begin
        if (!async_rst_n)
        if (!async_rst_n)
          begin
          begin
             for (i=0;i<size;i=i+1) fifo_mem[i] <= 0;
             for (i=0;i<size;i=i+1) fifo_mem[i] <= 0;
             wr_ptr <= 0;
             wr_ptr <= 0;
             ctr <= 0;
             ctr <= 0;
          end
          end
        else
        else
          begin
          begin
             fifo_mem[wr_ptr] <= psh_d;
             fifo_mem[wr_ptr] <= psh_d;
             wr_ptr <= #1 wr_ptr + 1;
             wr_ptr <= #1 wr_ptr + 1;
             ctr <= ctr + 1;
             ctr <= ctr + 1;
          end
          end
     end
     end
 
 
 
 
endmodule // generic_fifo
endmodule // generic_fifo
 
 
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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