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

Subversion Repositories openrisc

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

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 44 Rev 49
Line 42... Line 42...
module smii_phy
module smii_phy
  (
  (
   // SMII
   // SMII
    input     smii_tx,
    input     smii_tx,
    input     smii_sync,
    input     smii_sync,
    output    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,
Line 88... Line 88...
 
 
   /* 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 */
 
   wire [7:0] state_shiftreg_top_byte;
 
   assign state_shiftreg_top_byte[7:0] = state_shiftreg[10:3];
 
 
   always @(posedge clk)
   always @(posedge clk)
     begin
     begin
        if (!rst_n)
        if (!rst_n)
          begin
          begin
             state_shiftreg <= 10'b0000000001;
             state_shiftreg <= 10'b0000000001;
Line 125... Line 129...
               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
     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 rx_nibble_sel, rx_byte_valid;
   reg [7:0] rx_data_byte_rx_clk;
   reg [7:0] rx_data_byte_rx_clk;
 
 
   /* Receive the RX data from the PHY and serialise it */
   reg [4:0] rx_dv_nib_0;
   /* If RX data valid goes high, then it's the beginning of a
   reg       rx_nib_first,rx_nib_first_r;  // if high, nib_0 contains the "first" of the pair of nibs
    proper data segment*/
   reg [3:0] rx_segment_begin_num;
 
 
 
   // Allow us to check if RX DV has been low for a while
 
   reg [3:0] rx_dv_long_low_sr;
 
   wire      dv_long_low;
 
   always @(posedge ethphy_mii_rx_clk)
 
     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);
 
   reg      rx_dv;
 
   wire [8:0] rx_fifo_out;
 
   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_nibble_sel <= 0; /* start with low nibble receiving */
             rx_dv_nib_0 <= 0;
             rx_data_byte_rx_clk <= 0;
             rx_nib_first <= 0;
             rx_byte_valid <= 0;
             rx_nib_first_r <= 0;
          end
          end
        else
        else
          begin
          begin
             /* Half way through, and at the end of each 10-bit section
             if (!rx_nib_first)
              and whenever we should load a new segment (each time for
               rx_dv_nib_0 <= {ethphy_mii_rx_dv,ethphy_mii_rx_d};
              fast ethernet, else once every 10 times; whenever segment_ctr
             if(ethphy_mii_rx_dv)
              is 0)*/
               rx_nib_first <= ~rx_nib_first;
             //if ((state_shiftreg[6] | state_shiftreg[10]) & (segment_ctr==4'h0))
 
             //  begin
 
                  /* Alternate the nibble we're selecting when RX_dv */
 
                  if(!ethphy_mii_rx_dv) /* data on rx line is not valid */
 
                    rx_nibble_sel <= 0;
 
                  else
 
                    rx_nibble_sel <= ~rx_nibble_sel;
 
 
 
                  if (!ethphy_mii_rx_dv & !rx_nibble_sel)
             rx_nib_first_r <= rx_nib_first;
                    rx_byte_valid <= 0;
 
                  else if (rx_nibble_sel) /* sampled high nibble, byte OK*/
 
                    rx_byte_valid <= 1;
 
 
 
                  if (ethphy_mii_rx_dv & !rx_nibble_sel)
 
                    /* Sampling low nibble */
 
                    rx_data_byte_rx_clk[3:0] <= ethphy_mii_rx_d;
 
                  else if (ethphy_mii_rx_dv & rx_nibble_sel)
 
                    /* Sample high nibble */
 
                    rx_data_byte_rx_clk[7:4] <= ethphy_mii_rx_d;
 
 
 
               //end // if ((state_shiftreg[4] | state_shiftreg[9]) & (segment_ctr==4'h0))           
          end
          end // else: !if(!rst_n)
     end // always @ (posedge ethphy_mii_rx_clk or negedge rst_n)
     end // always @ (posedge clk)'
 
 
 
   /* SMII domain RX signals */
     always @(posedge clk or negedge rst_n)
   reg [7:0] rx_data_byte;
       begin
   reg rx_line_rx_dv; /* Reg for second bit of SMII RX sequence, RX_DV */
          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;
 
 
   /* A wire hooked up from bit 0 with the last byte of the state counter/shiftreg */
          rx_dv <= (state_shiftreg[10] & (((rx_segment_begin_num == (segment_ctr-1)) && !fast_ethernet)| fast_ethernet)) ? (rx_fifo_pop) : rx_dv;
   wire [7:0] state_shiftreg_top_byte;
       end
   assign state_shiftreg_top_byte[7:0] = state_shiftreg[10:3];
 
 
 
   /* Move RX's DV and data into SMII clk domain */
 
   always @(posedge clk)
   always @(posedge clk)
     begin
     begin
        if(!rst_n)
        /* remember which counter value we were at when rx enable/valid
          begin
         went high.
             rx_line_rx_dv <= 0;
         This is only useful when not doing fast ethernet*/
          end
 
        else
        /* rx en has gone high - remember the sequence number we're in */
          begin
        if ((rx_segment_begin_num == 4'hf) & (~rx_dv_long_low))
             /* When we're at the beginning of a new 10-bit sequence and
          rx_segment_begin_num <= segment_ctr;
              the beginning of the 10-segment loop load the valid bit */
 
             if(state_shiftreg[1] & (segment_ctr==4'h0))
        /* If rx enable goes low again, reset the segment number */
               begin
        if (rx_dv_long_low)
                  rx_line_rx_dv <= rx_byte_valid;
             /* reset to 0xf */
                  rx_data_byte <= rx_data_byte_rx_clk;
             rx_segment_begin_num <= 4'hf;
               end
               end
          end // else: !if(!rst_n)
 
     end // always @ (posedge clk)
 
 
 
 
     /* A fifo, storing RX bytes coming from the PHY interface */
 
   generic_fifo #(9, 64) rx_fifo
 
     (
 
      // Outputs
 
      .psh_full                         (),
 
      .pop_q                            (rx_fifo_out),
 
      .pop_empty                        (rx_fifo_empty),
 
      .almost_empty                     (rx_fifo_almost_empty),
 
      // Inputs
 
      .async_rst_n                      (rst_n),
 
      .psh_clk                          (ethphy_mii_rx_clk),
 
      .psh_we                           (rx_nib_first_r),
 
      .psh_d                            ({ethphy_mii_rx_err,ethphy_mii_rx_d,rx_dv_nib_0[3:0]}),
 
      .pop_clk                          (clk),
 
      .pop_re                           ((state_shiftreg[1] & rx_fifo_pop)&(((rx_segment_begin_num == segment_ctr) && !fast_ethernet)| fast_ethernet)));
 
 
 
 
 
  `ifdef RX_SYNC_1
 
 
   /* Assign the rx line out */
   /* Assign the rx line out */
   assign smii_rx = state_shiftreg[1] ? ethphy_mii_crs : /* 1st bit is MII CRS */
   always @(posedge clk)
                    /* next is RX_DV bit */
    smii_rx <= state_shiftreg[1] ? ethphy_mii_crs : /* 1st bit is MII CRS */
                    state_shiftreg[2] ? ((rx_byte_valid & (segment_ctr==4'h0)) |
                    state_shiftreg[2] ? ((rx_dv & (segment_ctr==4'h0) & !fast_ethernet) |
                                         rx_line_rx_dv) :
                                         rx_dv) :
                    /* Depending on RX_DV, output the status byte or data byte */
               // inter-frame status byte or data byte
                    rx_line_rx_dv ? |(state_shiftreg_top_byte & rx_data_byte) :
               state_shiftreg[3] ? (rx_dv ?  (rx_fifo_out[0]) : ethphy_mii_rx_err) :
                    /* Output status byte */
               state_shiftreg[4] ? (rx_dv ?  (rx_fifo_out[1]) : fast_ethernet) :
                    |(state_shiftreg_top_byte &
               state_shiftreg[5] ? (rx_dv ?  (rx_fifo_out[2]) : duplex) :
 
               state_shiftreg[6] ? (rx_dv ?  (rx_fifo_out[3]) : link) :
 
               state_shiftreg[7] ? (rx_dv ?  (rx_fifo_out[4]) : jabber) :
 
               state_shiftreg[8] ? (rx_dv ?  (rx_fifo_out[5]) : 1) :
 
               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)
 
    smii_rx <= state_shiftreg[10] ? ethphy_mii_crs : /* 1st bit is MII CRS */
 
                    state_shiftreg[1] ? ((rx_dv & (segment_ctr==4'h0) & !fast_ethernet) |
 
                                         rx_dv) :
 
               // inter-frame status byte or data byte
 
               state_shiftreg[2] ? (rx_dv ?  (rx_fifo_out[0]) : ethphy_mii_rx_err) :
 
               state_shiftreg[3] ? (rx_dv ?  (rx_fifo_out[1]) : fast_ethernet) :
 
               state_shiftreg[4] ? (rx_dv ?  (rx_fifo_out[2]) : duplex) :
 
               state_shiftreg[5] ? (rx_dv ?  (rx_fifo_out[3]) : link) :
 
               state_shiftreg[6] ? (rx_dv ?  (rx_fifo_out[4]) : jabber) :
 
               state_shiftreg[7] ? (rx_dv ?  (rx_fifo_out[5]) : 1) :
 
               state_shiftreg[8] ? (rx_dv ?  (rx_fifo_out[6]) : 0) :
 
               state_shiftreg[9] ? (rx_dv ?  (rx_fifo_out[7]) : 1) : 0;
 
  `endif // !`ifdef RX_SYNC_1
 
 
 
 
   /* 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,fast_ethernet,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 */
/**************************************************************************/
/**************************************************************************/
 
 
Line 227... Line 270...
   /* 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 [1: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;
   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;
 
   wire [3:0] tx_segment_load_num;
 
 
 
   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 = ((((!fast_ethernet) & (segment_ctr==4'h1)) |
   assign tx_seqbits_copy = (
                              ((fast_ethernet) & (state_shiftreg[1])))
                             (
                             & tx_en_seqbit_scratch);
                              ((!fast_ethernet) & (segment_ctr == tx_segment_load_num)) |
 
                              fast_ethernet
 
                             )
 
                             & tx_en_seqbit_scratch & state_shiftreg[1]
 
                            );
 
 
 
   always @(posedge clk)
 
     begin
 
        /* remember which counter value we were at when tx enable/valid
 
         went high.
 
         This is only useful when not doing fast ethernet*/
 
 
 
        /* tx en has gone high - remember the sequence number we're in */
 
        if ((tx_segment_begin_num == 4'hf) & (tx_en_seqbit_scratch))
 
          tx_segment_begin_num <= segment_ctr;
 
 
 
        /* If tx enable goes low again, reset the segment number */
 
        if (!tx_en_seqbit_scratch)
 
             /* reset to 0xf */
 
             tx_segment_begin_num <= 4'hf;
 
     end
 
 
 
 
   always @(posedge clk)
   always @(posedge clk)
     begin
     begin
        if (!rst_n)
        if (!rst_n)
          begin
          begin
Line 254... Line 321...
             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 (segment_ctr==4'h0)
 
               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;
Line 270... Line 335...
                   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 // if (segment_ctr==4'h0)
 
 
 
             /* If we've just received a sequence with TX_EN then put
 
              these values in the proper regs at the appropriate time,
 
              depending on the speed , ready for transmission to the PHY */
 
             if (tx_seqbits_copy)
 
               begin
 
 
 
                  /* Now clear the tx_en scratch bit so we don't do
 
                   this again */
 
                  tx_en_seqbit_scratch <= 0;
 
 
 
               end // if (tx_seqbits_copy)
 
          end
          end
     end // always @ (posedge clk)
     end // always @ (posedge clk)
 
 
 
   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
Line 303... Line 358...
             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(!tx_fifo_empty) /* A byte ready to go to the MAC */
              otherwise, we push out the byte each time we get one */
 
             //if((!tx_fifo_empty && !fast_ethernet) ||
 
             //(tx_fifo_full && fast_ethernet))
 
             if (!tx_fifo_almost_empty)
               begin
               begin
                  if(tx_byte_to_phy == 2'b00)
                  if(tx_byte_to_phy == 0)
                    begin
                    begin
                       /* Pop */
                       tx_byte_to_phy <= 1;
                       tx_fifo_pop <= 1;
                       tx_fifo_pop <= 1;
                       tx_byte_to_phy <= 2'b01;
 
                    end
                    end
               end
               end
 
 
             /* FIFO control loop */
             /* FIFO control loop */
             if (tx_byte_to_phy == 2'b01) /* Output bits 3-0 (bottom nibble ) */
             if (tx_byte_to_phy == 1)/* Output bits 3-0 (bottom nibble ) */
               begin
               begin
                  ethphy_mii_tx_d <= tx_fifo_q_dat[3:0];
 
                  ethphy_mii_tx_en <= 1;
                  ethphy_mii_tx_en <= 1;
                  ethphy_mii_tx_err <= tx_fifo_q_err;
 
                  tx_fifo_pop <= 0;
                  tx_fifo_pop <= 0;
                  tx_byte_to_phy <= 2'b10;
 
 
                  tx_byte_to_phy <= 2;
 
 
 
                  ethphy_mii_tx_d <= tx_fifo_q_dat[3:0];
 
                  nib <= tx_fifo_q_dat[7:4];
 
                  ethphy_mii_tx_err <= tx_fifo_q_err;
 
 
               end
               end
             else if (tx_byte_to_phy == 2'b10) /* 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;
 
 
                  if(!tx_fifo_empty) /* Check if more in FIFO */
                  if(!tx_fifo_empty) /* Check if more in FIFO */
                    begin
                    begin
                       tx_fifo_pop <= 1; /* Pop again */
                       tx_fifo_pop <= 1;
                       tx_byte_to_phy <= 2'b01;
                       tx_byte_to_phy <= 1;
                    end
                    end
                  else /* Finish up */
                  else /* Finish up */
                    begin
                    begin
                       tx_byte_to_phy <= 2'b11;
                       tx_byte_to_phy <= 3;
 
                       ethphy_mii_tx_en <= 0;
                    end
                    end
               end
               end
             else if (tx_byte_to_phy == 2'b11) /* De-assert TX_EN */
             else if (tx_byte_to_phy == 3) /* De-assert TX_EN */
               begin
               begin
                  ethphy_mii_tx_en <= 0;
 
                  tx_byte_to_phy <= 2'b00;
                  tx_byte_to_phy <= 2'b00;
               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)
 
 
Line 351... Line 417...
     (
     (
      // 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),
      // 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                          (),
      .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);
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 = 64;
   parameter size = 16;
 
   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 */
Line 384... Line 452...
   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              pop_empty;
   output              pop_empty;
 
   output wire         almost_empty;
 
 
 
 
   /* Actual FIFO memory */
   /* Actual FIFO memory */
   reg [dw-1:0]   fifo_mem [0:size-1];
   reg [dw-1:0]   fifo_mem [0:size-1];
 
 
   /* Poorly defined pointer logic -- will need to be changed if the size paramter is too big - Verilog needs some log base 2 thing */
 
   reg [7:0]   ptr; /* Only 8 bits, so max size of 255 of fifo! */
 
 
 
 
   /* FIFO position ptr regs */
 
   reg [size_log_2 - 1 : 0 ]   wr_ptr, rd_ptr, ctr;
 
 
   /* FIFO full signal for push side */
   integer     i;
   assign psh_full = (ptr == size-1) ? 1 : 0;
 
   /* FIFO empty signal for pop side */
 
   assign pop_empty = (ptr == 0) ? 1 : 0;
 
 
 
 
 
   /* This will work if pushing side is a lot faster than popping side */
   /* FIFO full signal for push side */
   reg         pop_re_psh_clk;
   //assign psh_full = (ptr == size-1) ? 1 : 0;
   wire       pop_re_risingedge_psh_clk; /* Signal to help push side see when
   /* This full logic means we all but one slot in the FIFO */
                                            there's been a pop_re rising edge,
   assign psh_full = ctr == size;
                                            sampled on push clock */
 
 
 
   /* Detect edge of signal in pop domain for psh domain */
   /* FIFO empty signal for pop side */
   assign pop_re_risingedge_psh_clk = (pop_re & !pop_re_psh_clk);
   //assign pop_empty = (ptr == 0) ? 1 : 0;
 
   //assign pop_empty = ctr==0;
 
   assign pop_empty = rd_ptr == wr_ptr;
 
 
 
   assign almost_empty = ctr < 2;
 
 
   integer    i;
   always @(posedge pop_re or negedge async_rst_n)
   always @(posedge psh_clk or negedge async_rst_n)
 
     begin
     begin
        if (!async_rst_n)
        if (!async_rst_n)
 
          rd_ptr <= 0;
 
        else
          begin
          begin
             ptr <= 0;
             pop_q = fifo_mem[rd_ptr];
 
             rd_ptr <= rd_ptr + 1;
 
             ctr <= ctr - 1;
 
          end
 
     end
 
 
 
   always @(posedge psh_we or negedge async_rst_n)
 
     begin
 
        if (!async_rst_n)
 
          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;
             pop_re_psh_clk <= 0;
             ctr <= 0;
 
 
          end
          end
        else
        else
          begin
          begin
 
             fifo_mem[wr_ptr] <= psh_d;
             pop_re_psh_clk <= pop_re; /* Register pop command in psh domain */
             wr_ptr <= #1 wr_ptr + 1;
 
             ctr <= ctr + 1;
             if (psh_we) /* Push into FIFO */
          end
               begin
 
                  if (!pop_re_psh_clk) /* If no pop at the same time, simple */
 
                    begin
 
                       fifo_mem[ptr] <= psh_d;
 
                       ptr <= ptr + 1'b1;
 
                    end
                    end
                  else /* Pop at same edge */
 
                    begin
 
                       /* Shift fifo contents */
 
                       for(i=1;i<size;i=i+1)
 
                         fifo_mem[i-1] <= fifo_mem[i];
 
                       fifo_mem[size-1] <= 0;
 
                       pop_q <= fifo_mem[0];
 
                       fifo_mem[ptr] <= psh_d;
 
                       /* ptr remains unchanged */
 
                    end // else: !if!(pop_re_psh_clk)
 
               end // if (psh_we)
 
             else /* No push, see if there's a pop */
 
               begin
 
                  if (pop_re_risingedge_psh_clk) /* Detected a pop */
 
                    begin
 
                       for(i=1;i<size;i=i+1)
 
                         fifo_mem[i-1] <= fifo_mem[i];
 
                       fifo_mem[size-1] <= 0;
 
                       pop_q <= fifo_mem[0];
 
                       ptr <= ptr - 1'b1;
 
                    end
 
               end // else: !if(psh_we)      
 
          end // else: !if(!async_rst_n)
 
     end // always @ (posedge psh_clk or negedge async_rst_n)
 
 
 
 
 
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.