commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r6500 - in gnuradio/branches/developers/matt/u2f/eth/r


From: matt
Subject: [Commit-gnuradio] r6500 - in gnuradio/branches/developers/matt/u2f/eth/rtl/verilog: . MAC_rx
Date: Thu, 20 Sep 2007 18:01:28 -0600 (MDT)

Author: matt
Date: 2007-09-20 18:01:28 -0600 (Thu, 20 Sep 2007)
New Revision: 6500

Modified:
   gnuradio/branches/developers/matt/u2f/eth/rtl/verilog/MAC_rx.v
   gnuradio/branches/developers/matt/u2f/eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v
Log:
bulk of changes for properly handling packet reception errors, from Claus


Modified: 
gnuradio/branches/developers/matt/u2f/eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v
===================================================================
--- gnuradio/branches/developers/matt/u2f/eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v  
2007-09-20 23:59:05 UTC (rev 6499)
+++ gnuradio/branches/developers/matt/u2f/eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v  
2007-09-21 00:01:28 UTC (rev 6500)
@@ -65,10 +65,12 @@
 MRxErr  ,       //  
 //CRC_chk interface                                 
 CRC_en    ,                                 
+CRC_data,
 CRC_init  ,
 CRC_err  ,                      
 //MAC_rx_add_chk interface                          
 MAC_add_en          ,                         
+MAC_add_data,
 MAC_rx_add_chk_err  ,   
 //broadcast_filter     
 broadcast_ptr   ,      
@@ -80,6 +82,7 @@
 Fifo_data       ,                             
 Fifo_data_en    ,                             
 Fifo_data_err   ,  
+Fifo_data_drop  ,
 Fifo_data_end   ,  
 Fifo_full       ,                          
 //RMON interface                
@@ -102,9 +105,11 @@
                 //CRC_chk interface
 output          CRC_en  ;       
 output          CRC_init;       
+output [7:0]    CRC_data;
 input           CRC_err ;
                 //MAC_rx_add_chk interface
 output          MAC_add_en          ;
+output [7:0]    MAC_add_data;
 input           MAC_rx_add_chk_err  ;
                 //broadcast_filter
 output          broadcast_ptr           ;
@@ -116,6 +121,7 @@
 output  [7:0]   Fifo_data       ;
 output          Fifo_data_en    ;
 output          Fifo_data_err   ;
+output          Fifo_data_drop  ;
 output          Fifo_data_end   ;
 input           Fifo_full;
                 //RMON interface
@@ -137,12 +143,13 @@
 parameter       State_data          =4'd03;
 parameter       State_checkCRC      =4'd04;
 parameter       State_OkEnd         =4'd07;
-parameter       State_drop          =4'd08;
+parameter       State_DropEnd       =4'd08;
 parameter       State_ErrEnd        =4'd09;
 parameter       State_CRCErrEnd     =4'd10;
 parameter       State_FFFullDrop    =4'd11;
 parameter       State_FFFullErrEnd  =4'd12;
 parameter       State_IFG           =4'd13;
+parameter       State_Drop2End      =4'd14;
 
 parameter       Pause_idle          =4'd0;   
 parameter       Pause_pre_syn       =4'd1;    
@@ -162,14 +169,14 @@
 reg [15:0]      Frame_length_counter;
 reg             Too_long;
 reg             Too_short;
-reg             Fifo_data_en;
-reg             Fifo_data_end;
-reg             Fifo_data_err;
+reg             ProcessingHeader;
+//reg             Fifo_data_en;
+//reg             Fifo_data_err;
+//reg             Fifo_data_drop;
+//reg             Fifo_data_end;
 reg             CRC_en;
 reg             CRC_init;
 reg             Rx_apply_rmon;
-reg             Rx_apply_rmon_tmp;
-reg             Rx_apply_rmon_tmp_pl1;
 reg [2:0]       Rx_pkt_err_type_rmon;
 reg             MAC_add_en;
 reg [2:0]       Rx_pkt_type_rmon;
@@ -203,119 +210,233 @@
     else 
         RxD_dl1     <=RxD;
                                    
+//---------------------------------------------------------------------------
+// Small pre-FIFO (acutally a synchronously clearable shift-register) for
+// storing the first part of a packet before writing it to the "real" FIFO
+// in MAC_rx_FF. This allows a packet to be dropped safely if an error
+// happens in the beginning of a packet (or if the MAC address doesn't pass
+// the receive filter!)
+//---------------------------------------------------------------------------
+
+  reg           pre_fifo_data_drop;
+  reg           pre_fifo_data_en;
+  reg           pre_fifo_data_err;
+  reg           pre_fifo_data_end;
+  wire [7:0]    pre_fifo_wrdata;
+
+  reg [8+3-1:0] pre_fifo_element_0;
+  reg [8+3-1:0] pre_fifo_element_1;
+  reg [8+3-1:0] pre_fifo_element_2;
+  reg [8+3-1:0] pre_fifo_element_3;
+  reg [8+3-1:0] pre_fifo_element_4;
+  reg [8+3-1:0] pre_fifo_element_5;
+  reg [8+3-1:0] pre_fifo_element_6;
+  reg [8+3-1:0] pre_fifo_element_7;
+  reg [8+3-1:0] pre_fifo_element_8;
+  reg [8+3-1:0] pre_fifo_element_9;
+
+  always @( posedge Reset or posedge Clk )
+    if ( Reset )
+      begin
+        pre_fifo_element_0 <= 'b0;
+        pre_fifo_element_1 <= 'b0;
+        pre_fifo_element_2 <= 'b0;
+        pre_fifo_element_3 <= 'b0;
+        pre_fifo_element_4 <= 'b0;
+        pre_fifo_element_5 <= 'b0;
+        pre_fifo_element_6 <= 'b0;
+        pre_fifo_element_7 <= 'b0;
+        pre_fifo_element_8 <= 'b0;
+        pre_fifo_element_9 <= 'b0;
+      end
+    else
+      begin
+        if ( pre_fifo_data_drop )
+          begin
+            pre_fifo_element_0 <= 'b0;
+            pre_fifo_element_1 <= 'b0;
+            pre_fifo_element_2 <= 'b0;
+            pre_fifo_element_3 <= 'b0;
+            pre_fifo_element_4 <= 'b0;
+            pre_fifo_element_5 <= 'b0;
+            pre_fifo_element_6 <= 'b0;
+            pre_fifo_element_7 <= 'b0;
+            pre_fifo_element_8 <= 'b0;
+            pre_fifo_element_9 <= 'b0;
+          end
+        else
+          begin
+            pre_fifo_element_0 <= pre_fifo_element_1;
+            pre_fifo_element_1 <= pre_fifo_element_2;
+            pre_fifo_element_2 <= pre_fifo_element_3;
+            pre_fifo_element_3 <= pre_fifo_element_4;
+            pre_fifo_element_4 <= pre_fifo_element_5;
+            pre_fifo_element_5 <= pre_fifo_element_6;
+            pre_fifo_element_6 <= pre_fifo_element_7;
+            pre_fifo_element_7 <= pre_fifo_element_8;
+            pre_fifo_element_8 <= pre_fifo_element_9;
+            pre_fifo_element_9 <= { pre_fifo_data_en,
+                                    pre_fifo_data_err,
+                                    pre_fifo_data_end,
+                                    pre_fifo_wrdata };
+          end
+      end
+
+  assign Fifo_data     = pre_fifo_element_0[7:0];
+  assign Fifo_data_end = pre_fifo_element_0[8];
+  assign Fifo_data_err = pre_fifo_element_0[9];
+  assign Fifo_data_en  = pre_fifo_element_0[10];
+
+  assign CRC_data     = pre_fifo_wrdata;
+  assign MAC_add_data = pre_fifo_wrdata;
+
 
//******************************************************************************
 //State_machine                                                           
 
//******************************************************************************
                                                     
-always @ (posedge Reset or posedge Clk)                 
-    if (Reset)                                          
-        Current_state   <=State_idle;                   
-    else                                    
-        Current_state   <=Next_state;                   
-                                                        
-always @ (*)                                             
-        case (Current_state)                            
-            State_idle:
-                    if (Crs_dv&&RxD==8'h55)                
-                        Next_state  =State_preamble;    
-                    else                                
-                        Next_state  =Current_state;     
-            State_preamble:                             
-                    if (!Crs_dv)                        
-                        Next_state  =State_ErrEnd;      
-                    else if (RxErr)                     
-                        Next_state  =State_drop;        
-                    else if (RxD==8'hd5)                 
-                        Next_state  =State_SFD;                 
-                    else if (RxD==8'h55)                
-                        Next_state  =Current_state;     
-                    else                                
-                        Next_state  =State_drop;        
-            State_SFD:                                  
-                    if (!Crs_dv)                        
-                        Next_state  =State_ErrEnd;      
-                    else if (RxErr)                     
-                        Next_state  =State_drop;        
-                    else                                
-                        Next_state  =State_data;       
-            State_data:                                
-                    if (!Crs_dv&&!Too_short&&!Too_long)                        
-                        Next_state  =State_checkCRC;   
-                    else if (!Crs_dv&&(Too_short||Too_long))
-                        Next_state  =State_ErrEnd;
-                    else if (Fifo_full)
-                        Next_state  =State_FFFullErrEnd;
-                    else if 
(RxErr||MAC_rx_add_chk_err||Too_long||broadcast_drop)                     
-                        Next_state  =State_drop;        
-                    else                                
-                        Next_state  =State_data;       
-            State_checkCRC:
-                     if (CRC_err)
-                        Next_state  =State_CRCErrEnd;
-                     else
-                        Next_state  =State_OkEnd; 
-            State_drop:                                 
-                    if (!Crs_dv)                        
-                        Next_state  =State_ErrEnd;      
-                    else                                
-                        Next_state  =Current_state;     
-            State_OkEnd:                                
-                        Next_state  =State_IFG;         
-            State_ErrEnd:                               
-                        Next_state  =State_IFG;       
-                                                                            
-            State_CRCErrEnd:                               
-                        Next_state  =State_IFG;   
-            State_FFFullDrop:
-                    if (!Crs_dv)                        
-                        Next_state  =State_IFG;     
-                    else                                
-                        Next_state  =Current_state;                            
                    
-            State_FFFullErrEnd:
-                        Next_state  =State_FFFullDrop;                         
               
-            State_IFG:                                  
-                    if (IFG_counter==RX_IFG_SET-4)   //remove some additional 
time     
-                        Next_state  =State_idle;        
-                    else                                
-                        Next_state  =Current_state;     
-                                                        
-            default:                                    
-                        Next_state  =State_idle;        
-        endcase                                         
-                     
-                                                        
-always @ (posedge Reset or posedge Clk)                 
-    if (Reset)                                          
-        IFG_counter     <=0;   
-    else if (Current_state!=State_IFG)
-        IFG_counter     <=0;                                
-    else 
-        IFG_counter     <=IFG_counter + 1;
+always @( posedge Reset or posedge Clk )
+  if ( Reset )
+    Current_state <= State_idle;
+  else
+    Current_state <= Next_state;
+
+always @ (*)
+  case (Current_state)
+    State_idle:
+      if ( Crs_dv&&RxD==8'h55 )
+        Next_state = State_preamble;
+      else
+        Next_state = Current_state;
+
+    State_preamble:
+      if ( !Crs_dv )
+        Next_state = State_DropEnd;
+      else if ( RxErr )
+        Next_state = State_DropEnd;
+      else if ( RxD==8'hd5 )
+        Next_state = State_SFD;
+      else if ( RxD==8'h55 )
+        Next_state =Current_state;
+      else
+        Next_state = State_DropEnd;
+
+    State_SFD:
+      if ( !Crs_dv )
+        Next_state = State_DropEnd;
+      else if ( RxErr )
+        Next_state = State_DropEnd;
+      else
+        Next_state = State_data;
+
+    State_data:
+      if ( !Crs_dv && !ProcessingHeader && !Too_short && !Too_long )
+        Next_state = State_checkCRC;
+      else if ( !Crs_dv && ProcessingHeader )
+        Next_state = State_Drop2End;
+      else if ( !Crs_dv && (Too_short | Too_long) )
+        Next_state = State_ErrEnd;
+       else if ( Fifo_full )
+         Next_state = State_FFFullErrEnd;
+       else if ( RxErr && ProcessingHeader )
+         Next_state = State_Drop2End;
+       else if ( RxErr || Too_long )
+         Next_state = State_ErrEnd;
+       else if ( MAC_rx_add_chk_err || broadcast_drop )
+         Next_state = State_DropEnd;
+       else
+         Next_state = State_data;
+
+    State_checkCRC:
+      if ( CRC_err )
+        Next_state = State_CRCErrEnd;
+      else
+        Next_state = State_OkEnd;
+
+    State_OkEnd:
+      Next_state = State_IFG;
+
+    State_ErrEnd:
+      Next_state = State_IFG;
+
+    State_DropEnd:
+      Next_state = State_IFG;
+
+    State_Drop2End:
+      Next_state = State_IFG;
+
+    State_CRCErrEnd:
+      Next_state = State_IFG;
+
+    State_FFFullErrEnd:
+      Next_state = State_FFFullDrop;
+
+    State_FFFullDrop:
+      if ( !Crs_dv )
+        Next_state  =State_IFG;     
+      else                                
+        Next_state  =Current_state;                                            
    
+
+    State_IFG:
+      if ( IFG_counter==RX_IFG_SET-4 ) // Remove some additional time?
+        Next_state = State_idle;
+      else
+        Next_state = Current_state;
+
+    default:
+      Next_state = State_idle;
+  endcase
+
+always @( posedge Reset or posedge Clk )
+  if ( Reset )
+    IFG_counter <= 0;
+  else if ( Current_state!=State_IFG )
+    IFG_counter <= 0;
+  else
+    IFG_counter <= IFG_counter + 1;
+
 
//******************************************************************************
 //gen fifo interface signals                                                   
  
 
//******************************************************************************
                     
 
-assign  Fifo_data   =RxD_dl1;       
+assign pre_fifo_wrdata = RxD_dl1;
 
-always @(Current_state)
-    if  (Current_state==State_data)
-        Fifo_data_en        =1;
-    else
-        Fifo_data_en        =0;
+always @( Current_state )
+  if ( Current_state==State_data )
+    pre_fifo_data_en = 1;
+  else
+    pre_fifo_data_en = 0;
         
-always @(Current_state)
-    if  (Current_state==State_ErrEnd||Current_state==State_OkEnd
-         ||Current_state==State_CRCErrEnd||Current_state==State_FFFullErrEnd)
-        Fifo_data_end       =1;
-    else
-        Fifo_data_end       =0;
+always @( Current_state )
+  if ( (Current_state==State_ErrEnd      ) ||
+       (Current_state==State_OkEnd       ) ||
+       (Current_state==State_CRCErrEnd   ) ||
+       (Current_state==State_FFFullErrEnd) ||
+       (Current_state==State_DropEnd     ) ||
+       (Current_state==State_Drop2End    ) )
+    pre_fifo_data_end = 1;
+  else
+    pre_fifo_data_end = 0;
 
-always @(Current_state)
-    if  
(Current_state==State_ErrEnd||Current_state==State_CRCErrEnd||Current_state==State_FFFullErrEnd)
-        Fifo_data_err       =1;
-    else
-        Fifo_data_err       =0;     
+always @( Current_state )
+  if ( (Current_state==State_ErrEnd      ) ||
+       (Current_state==State_CRCErrEnd   ) ||
+       (Current_state==State_FFFullErrEnd) ||
+       (Current_state==State_DropEnd     ) ||
+       (Current_state==State_Drop2End    ) )
+    pre_fifo_data_err = 1;
+  else
+    pre_fifo_data_err = 0;
 
+always @( Current_state )
+  if ( (Current_state==State_DropEnd ) ||
+       (Current_state==State_Drop2End) )
+    pre_fifo_data_drop = 1;
+  else
+    pre_fifo_data_drop = 0;
+
+  // Srop in main Rx FIFO is no longer supported!
+  assign Fifo_data_drop = 0;
+
 
//******************************************************************************
 //CRC_chk interface                                               
 
//******************************************************************************
 
@@ -343,6 +464,12 @@
     else if (Current_state==State_data)
         Frame_length_counter        <=Frame_length_counter+ 1'b1;
         
+always @( Frame_length_counter )
+  if ( Frame_length_counter < 8 )
+    ProcessingHeader = 1;
+  else
+    ProcessingHeader = 0;
+
 always @ (Frame_length_counter or RX_MIN_LENGTH)
     if (Frame_length_counter<RX_MIN_LENGTH)
         Too_short   =1;
@@ -355,31 +482,30 @@
     else
         Too_long    =0;
         
-assign Rx_pkt_length_rmon=Frame_length_counter-1'b1;
+assign Rx_pkt_length_rmon = Frame_length_counter-1'b1;
 
-always @ (posedge Clk or posedge Reset)
-    if (Reset)
-        Rx_apply_rmon_tmp   <=0; 
-    else if (Current_state==State_OkEnd||Current_state==State_ErrEnd
-        ||Current_state==State_CRCErrEnd||Current_state==State_FFFullErrEnd)
-        Rx_apply_rmon_tmp   <=1;        
-    else
-        Rx_apply_rmon_tmp   <=0; 
-        
-always @ (posedge Clk or posedge Reset)
-    if (Reset)
-        Rx_apply_rmon_tmp_pl1   <=0;
-    else
-        Rx_apply_rmon_tmp_pl1   <=Rx_apply_rmon_tmp;        
+reg [2:0] Rx_apply_rmon_reg;
 
-always @ (posedge Clk or posedge Reset)
-    if (Reset)
-        Rx_apply_rmon   <=0; 
-    else if (Current_state==State_OkEnd||Current_state==State_ErrEnd
-        ||Current_state==State_CRCErrEnd||Current_state==State_FFFullErrEnd)
-        Rx_apply_rmon   <=1;        
-    else if (Rx_apply_rmon_tmp_pl1)
-        Rx_apply_rmon   <=0; 
+always @( posedge Clk or posedge Reset )
+  if ( Reset )
+    begin
+      Rx_apply_rmon <= 0;
+      Rx_apply_rmon_reg <= 'b0;
+    end
+  else
+    begin
+      if ( (Current_state==State_OkEnd       ) ||
+           (Current_state==State_ErrEnd      ) ||
+           (Current_state==State_CRCErrEnd   ) ||
+           (Current_state==State_Drop2End    ) ||
+           (Current_state==State_FFFullErrEnd) )
+        Rx_apply_rmon <= 1;
+      else
+        if ( Rx_apply_rmon_reg[2] )
+          Rx_apply_rmon <= 0;
+
+      Rx_apply_rmon_reg <= { Rx_apply_rmon_reg[1:0], Rx_apply_rmon  };
+    end
         
 always @ (posedge Clk or posedge Reset)
     if (Reset)
@@ -388,7 +514,7 @@
         Rx_pkt_err_type_rmon    <=3'b001    ;//
     else if (Current_state==State_FFFullErrEnd)
         Rx_pkt_err_type_rmon    <=3'b010    ;// 
-    else if (Current_state==State_ErrEnd)
+    else if ( (Current_state==State_ErrEnd) || (Current_state==State_Drop2End) 
)
         Rx_pkt_err_type_rmon    <=3'b011    ;//
     else if(Current_state==State_OkEnd)
         Rx_pkt_err_type_rmon    <=3'b100    ;
@@ -416,9 +542,9 @@
 
//******************************************************************************
 //MAC add checker signals                                                      
        
 
//******************************************************************************
-always @ (Frame_length_counter or Fifo_data_en)
+always @ (Frame_length_counter or pre_fifo_data_en)
     if(Frame_length_counter>=1&&Frame_length_counter<=6)
-        MAC_add_en  <=Fifo_data_en;
+        MAC_add_en  <=pre_fifo_data_en;
     else
         MAC_add_en  <=0;
 
@@ -533,4 +659,4 @@
                 
 endmodule
                 
-                                                
\ No newline at end of file
+                                                

Modified: gnuradio/branches/developers/matt/u2f/eth/rtl/verilog/MAC_rx.v
===================================================================
--- gnuradio/branches/developers/matt/u2f/eth/rtl/verilog/MAC_rx.v      
2007-09-20 23:59:05 UTC (rev 6499)
+++ gnuradio/branches/developers/matt/u2f/eth/rtl/verilog/MAC_rx.v      
2007-09-21 00:01:28 UTC (rev 6500)
@@ -73,6 +73,7 @@
 output  [1:0]   Rx_mac_BE   ,
 output          Rx_mac_pa   ,
 output          Rx_mac_sop  ,
+output          Rx_mac_err  ,
 output          Rx_mac_eop  ,
                 //CPU
 input           MAC_rx_add_chk_en   ,   
@@ -100,10 +101,12 @@
 
//******************************************************************************
                 //CRC_chk interface
 wire            CRC_en  ;       
+wire    [7:0]   CRC_data;
 wire            CRC_init;       
 wire            CRC_err ;
                 //MAC_rx_add_chk interface
 wire            MAC_add_en          ;
+wire    [7:0]   MAC_add_data;
 wire            MAC_rx_add_chk_err  ;
                 //broadcast_filter
 wire            broadcast_ptr           ;
@@ -116,7 +119,10 @@
 wire            Fifo_data_en    ;
 wire            Fifo_full       ;
 wire            Fifo_data_err   ;
+wire            Fifo_data_drop  ;
 wire            Fifo_data_end   ;
+
+
 
//******************************************************************************
 //instantiation                                                            
 
//******************************************************************************
@@ -131,10 +137,12 @@
 .MRxErr                      (MRxErr                    ),                     
        
  //CRC_chk interface         (//CRC_chk interface       ),                     
                              
 .CRC_en                      (CRC_en                    ),                     
                     
+.CRC_data                    (CRC_data                  ),                     
                     
 .CRC_init                    (CRC_init                  ),                     
      
 .CRC_err                     (CRC_err                   ),                     
         
  //MAC_rx_add_chk interface  (//MAC_rx_add_chk interface),                     
                              
 .MAC_add_en                  (MAC_add_en                ),                     
                        
+.MAC_add_data                (MAC_add_data              ),
 .MAC_rx_add_chk_err          (MAC_rx_add_chk_err        ),                     
        
  //broadcast_filter          (//broadcast_filter        ),                     
      
 .broadcast_ptr               (broadcast_ptr             ),                     
    
@@ -146,6 +154,7 @@
 .Fifo_data                   (Fifo_data                 ),                     
                    
 .Fifo_data_en                (Fifo_data_en              ),                     
                    
 .Fifo_data_err               (Fifo_data_err             ),                     
    
+.Fifo_data_drop              (Fifo_data_drop            ),                     
    
 .Fifo_data_end               (Fifo_data_end             ),                     
    
 .Fifo_full                   (Fifo_full                 ),                     
                 
  //RMON interface            (//RMON interface          ),                     
          
@@ -168,6 +177,7 @@
 .Fifo_data_en                (Fifo_data_en              ),
 .Fifo_full                   (Fifo_full                 ),
 .Fifo_data_err               (Fifo_data_err             ),
+.Fifo_data_drop              (Fifo_data_drop            ),
 .Fifo_data_end               (Fifo_data_end             ),
  //CPU                       (//CPU                     ),
 .Rx_Hwmark                   (Rx_Hwmark                 ),
@@ -180,6 +190,7 @@
 .Rx_mac_BE                   (Rx_mac_BE                 ),
 .Rx_mac_sop                  (Rx_mac_sop                ), 
 .Rx_mac_pa                   (Rx_mac_pa                 ),
+.Rx_mac_err                  (Rx_mac_err                ),
 .Rx_mac_eop                  (Rx_mac_eop                ) 
 ); 
 
@@ -202,7 +213,7 @@
 CRC_chk U_CRC_chk(
 .Reset                      (Reset                      ),
 .Clk                        (Clk                        ),
-.CRC_data                   (Fifo_data                  ),
+.CRC_data                   (CRC_data                   ),
 .CRC_init                   (CRC_init                   ),
 .CRC_en                     (CRC_en                     ),
  //From CPU                 (//From CPU                 ),
@@ -215,7 +226,7 @@
 .Reset                      (Reset                      ),
 .Clk                        (Clk                        ),
 .Init                       (CRC_init                   ),
-.data                       (Fifo_data                  ),
+.data                       (MAC_add_data               ),
 .MAC_add_en                 (MAC_add_en                 ),
 .MAC_rx_add_chk_err         (MAC_rx_add_chk_err         ),
  //From CPU                 (//From CPU                 ),





reply via email to

[Prev in Thread] Current Thread [Next in Thread]