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

Subversion Repositories spacewire

[/] [spacewire/] [trunk/] [rtl/] [Receiver.v] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 btltz
//File name=Module=Receiver  2005-2-18      btltz@mail.china.com    btltz from CASIC  
2
//Description:   Receiver of the SpaceWire encoder-decoder.    
3
//Abbreviations: dsc  : disconnect
4
//Origin:        SpaceWire Std - Draft-1(Clause 8)of ECSS(European Cooperation for Space Standardization),ESTEC,ESA.
5
//--     TODO:    make rtl faster
6
////////////////////////////////////////////////////////////////////////////////////
7
//
8
/*synthesis translate off*/
9
`timescale 1ns/100ps
10
/*synthesis translate on */
11
`define gFreq  80
12
`define ErrorReset  6'b000001
13
`define ErrorWait   6'b000010
14
`define Ready       6'b000100
15
`define Started     6'b001000
16
`define Connecting  6'b010000
17
`define Run         6'b100000
18
`define reset  1         // WISHBONE standard reset
19
`define XIL_DEVICE //if use Xilinx Device
20
//`define HAS_FIFO_VECTOR_IN
21
`define HAS_RecCLK_O            //the recovery clock
22
 
23
module Receiver  //#(parameter DW=8)
24
                (output reg  gotBIT_o,
25
                             gotFCT_o,                        //Output to Transmitter and/or the FSM(PPU)
26
                             gotNchar_o,gotTIME_o,gotNULL_o,    //gotNull is a level,others are pulse
27
//5 receive error outputs.Note the err_sqc is formed in the PPU and err_crd is formed in Tx.Note that these are all "Receiver error".            
28
                 output reg err_par,err_esc,err_dsc,  //Pulse generated when has err                           
29
//  output RxErr_o,
30
                 output [5:0] osd_cnt_o,
31
                                          input Si,Di,  //Input from the LVDS's Receiver
32
                 input EnRx_i,  //from PPU
33
//Rx vs. Tx
34
                 input C_Send_FCT_i,   //for osd_cnt operation 
35
                                          output reg nedsFCT_o, //need sending FCT to info Tx
36
//interface to the FIFO
37
                 output reg wrtbuf_o,
38
                 output reg type_o,  //0(data) or 1(EOP or EEP)      
39
                 output reg[7:0] RxData_o,  //8 bit width parallel received data or control flag
40
                 input full_i,  //Indicate the buffer is ready to write
41
                                          `ifdef HAS_FIFO_VECTOR_IN
42
                 input[7:0] Vec_Rxfifo, //the number of the vector of the Rx fifo
43
                                          `endif
44
//Control and clk output
45
                 output reg Lnk_dsc_o,
46
                                          `ifdef HAS_RecCLK_O
47
                 output RecClk_o,   //the clk signal from the "RX clock recovery" unit which had been mergeed to the Receiver
48
                                          `endif
49
                                          output rx_strb_o,
50
//output time interface       
51
                 output reg TICK_OUT,
52
                 output reg [1:0] CtrlFlg_o, //two-bit control flag output.Reserved for future use.
53
                 output reg [5:0] TIMEout,
54
//global signal input
55
                 input[5:0] state_i,
56
                 input reset,   //this reset is from the CODEC FSM(the PPU)
57
                 input gclk /* synthesis syn_isclock = 1 */
58
                 );
59
         //At a link data signalling rate of 10 Mb/s the establish of linking can take just     2 ¦Ìs.
60
               parameter StateNum =3;
61
               parameter RESET         = 3'b001;
62
               parameter HUNTING       = 3'b010;
63
               parameter CHECK_CHAR    = 3'b100;
64
               parameter DEFLT = 'bx;
65
 
66
     parameter CrdCntW = 6;     //"hold a maximum credit count of 56" for 7 FCTs
67
     parameter RCVW = 14;       //width of the receiver internal register  
68
          parameter NUM_NES_FCT = 16;//osd_cnt number that indicate Rx buf has enough space and Tx need to send FCT.For better performence,this parameter may be changed 
69
          parameter True = 1;
70
     parameter False = 0;
71
   //Control characters.Go with a parity bit as their prefix(LSB).
72
     parameter FCT  = 3'b001, ESC  = 3'b111,   //"L-Char":Link-characters. 
73
               EOP  = 3'b101, EEP  = 3'b011;   //or Data-Char are all "N-Char":Normal-characters
74
     parameter NULL      = 7'b0010_111;
75
          parameter isESC_EEP = 7'b0110_111,
76
                    isESC_EOP = 7'b1010_111,
77
                    isESC_ESC = 7'b1110_111;
78
     parameter TIME_PATTERN = 5'b01111; //Go with a parity bit before and 8 bits time value from LSB 2 MSB after
79
     parameter NUM_DSC = 9;
80
 
81
reg [RCVW-1:0] rereg;  //posthouse,is the front end of the Rx to receive signal ceaselessly;
82
              // P /Flag/...data .../
83
//reg rereg1;  //Trace of the rereg[1]
84
 
85
 
86
reg [3:0] mccnt;
87
reg scover_pre;  //overflow of the model control counter          
88
reg scover; //1 clk later
89
//reg err_dsc;  //disconnect err.When no new data bit is received within a link disconnect timeoutwindow (850 ns)
90
 
91
reg p;  //register for parity generate
92
reg p_1;//keep the result of the Parity Generate  
93
//reg C_ParCheck;
94
 
95
reg [5:0] osd_cnt;   //count of the number of outstanding N-Chars it expects to receive
96
                  //Max(6bits) = 64,so crd_cnt[max] = 56 
97
assign  osd_cnt_o = osd_cnt;
98
reg CcTIME,CcNchar;       //command to collect time/Nchar from rereg for send
99
reg wrtbuf_itl; //wire in true
100
reg [StateNum-1:0] state,next_state/*synthesis syn_encoding="safe,onehot"*/;
101
 
102
wire isTIME= (rereg[5:1]==TIME_PATTERN) ?   1'b1  :  1'b0;
103
wire isEOP =  (rereg[3:1]==EOP ) ?  1'b1  :  1'b0;
104
wire isEEP =  (rereg[3:1]==EEP ) ?  1'b1  :  1'b0;
105
wire isFCT =  (rereg[3:1]==FCT ) ?  1'b1  :  1'b0;
106
wire isDATA = (rereg[1]==0)      ?  1'b1  :  1'b0;
107
wire isNULL    = (rereg[6:0]==NULL) ?  1'b1  :  1'b0; //quik combinatorial output for "mccnt" operation
108
wire isESC_ERR = (rereg[6:0]==isESC_EOP
109
                ||rereg[6:0]==isESC_EEP
110
                                         ||rereg[6:0]==isESC_ESC ) ?  1'b1  :  1'b0;
111
reg    isNULL_1,
112
       isEOP_1,
113
       isEEP_1,
114
       isFCT_1,
115
       isDATA_1,
116
       isTIME_1;
117
 
118
//wire pre_par_ok = (p==rereg[0])  ?  1'b1  :  1'b0; 
119
 
120
//..............................................................................
121
///////////////////////
122
// Rx clk recovery:    
123
//    Provides all the clock signals used by the receiver with the exception of the local clock signal use
124
//         for disconnect timeout.
125
//    Note that the "Si" and "Di" are all SYNchronoused to avoid the metastable
126
//           in FPGA so they are all orderly now !!!
127
reg strobe;
128
reg Si1,Di1;
129
wire RecClk = Si ^ Di;  //1 XOR
130
assign RecClk_o = RecClk;
131
 
132
always @(posedge gclk)
133
if(reset)
134
  {strobe,Si1,Di1} <= 0;
135
else
136
  begin
137
  Si1 <= Si;
138
  Di1 <= Di;
139
  strobe <= 0;
140
  if( (Si1 != Si)                       //   XOR 
141
     || (Di1 != Di) )           //                      \ OR---> strobe  
142
  strobe <= 1'b1;                               //                 /
143
                                                        //        XOR
144
  end
145
 
146
assign rx_strb_o = strobe;
147
 
148
// wire LocalRx_err = err_dsc || err_esc || err_par;   
149
 
150
 
151
//////////////////////
152
// Receive data 
153
//    and take that
154
always @(posedge  gclk )  //As long as RecCLK presences,store the received scan beam to the temp reg "rereg"
155
begin
156
 if(reset)
157
   rereg <= 0;
158
 else if(EnRx_i && strobe)
159
   begin
160
   rereg[mccnt] <= Di;
161
   // rereg1 <= rereg[1];   
162
   end
163
end
164
 
165
////////////////////////////////////////////////////////
166
//Parity Gen
167
//    and parity okey
168
 
169
//The new received parity bit is ready when scover==1 and is
170
//  reposited in rereg[0]
171
//The local generated p is ready when "CHECK_CHAR"
172
assign par_ok = (EnRx_i==1 && scover==1)  ? (p_1==rereg[0] ? 1 :0 ) :  0 ;
173
                                                 //Preliminary Check
174
always @(posedge gclk)
175
if(reset || scover_pre)
176
  p <= 1'b1;           //when scover_pre,refresh p,and the local parity result is stored in p_1
177
else if(strobe==True)
178
  begin
179
     p <= p ^ rereg[mccnt];
180
     p_1 <= p;
181
  end
182
 
183
//////////////////////
184
// osd_cnt assignment
185
//       
186
always @(posedge gclk)
187
begin
188
   if(reset || Lnk_dsc_o)
189
   begin
190
          nedsFCT_o <= 1;
191
          osd_cnt <= 0;            //After a link reset or after a link disconnect, the initial value of the outstanding
192
                         //count shall be zero. Means that the transmitter need to 
193
   end
194
        else begin
195
             if(osd_cnt>48)
196
                    nedsFCT_o <= 1'b0;      //level
197
        else    if(osd_cnt <= NUM_NES_FCT)
198
                    nedsFCT_o <= 1'b1;      //This event start the Tx to send FCTs
199
 
200
                  if(C_Send_FCT_i &&(osd_cnt < 49) )   //osd_cnt[max] <= 56  because 56+8>63   
201
        osd_cnt <= osd_cnt + 8;
202
        else if(gotNchar_o)                    //decrement by one each time an N-Char is received
203
        osd_cnt <= osd_cnt - 1;
204
                  end
205
end
206
 
207
//////////////////////////////////////
208
//RECEIVE model control counter
209
// for receive operation control
210
reg start_mccnt;
211
 
212
always @(posedge gclk)
213
if(reset) //reset from PPU when global reset or state_i==`ErrorReset
214
  {scover_pre,scover,mccnt,start_mccnt} <= 0;
215
else
216
   begin
217
     scover_pre <= 0;
218
     scover <= scover_pre;  //scover is the real overflow of "mccnt"
219
      if( (mccnt==2)&&( isFCT ||isEOP || isEEP )
220
         || (mccnt==6)&&( isNULL )//scover_pre is 1 clock earlier than the real overflow of the "mccnt"
221
         || (mccnt==8)&&( isDATA )//to quikly indicate that data in "rereg" is ready to check
222
         || (mccnt==12)&&( isTIME )  )
223
 
224
         scover_pre <= 1;
225
 
226
     start_mccnt <= 1;  //start_mccnt is 1 clock latency so "mccnt" can count as a normal counter and "0" indicates a data
227
     if( strobe &&
228
              ( (mccnt==3)&&( isFCT ||isEOP || isEEP )
229
         || (mccnt==7)&&( isNULL )
230
         || (mccnt==9)&&( isDATA )
231
         || (mccnt==13)&&( isTIME )  )
232
                 )
233
 
234
          mccnt <= 0;
235
     else if(start_mccnt && strobe)
236
       mccnt <= mccnt + 1'b1;
237
   end
238
 
239
   ///////////////////////////////////////////////////////
240
  //err_dsc  Generate      //when the length of time since the last transition on the D or S lines was
241
 //                       // longer than 850 ns nominal
242
////////////////////////////////////////////////////////
243
//If the disconnect error occurs in the Run state then the disconnect error shall
244
//be flagged up to the network level as a link error
245
 
246
reg[3:0] edcnt; //850ns = 8.5 * 100ns, so max = 9. (error_disconnect counter)
247
wire rst_edcnt = reset || RecClk;
248
always @(posedge gclk)
249
if(rst_edcnt)  //if Rec2CLK is high,clear "edcnt"
250
  {edcnt,err_dsc} <= 0;
251
else if(gotBIT_o==True)
252
     begin
253
          if(!RecClk)     //if Rec2CLK is low,increase the edcnt. If there is signal at D or S,Rec2CLK must appear!
254
      begin
255
       err_dsc <= 1'b0;
256
       if(edcnt==NUM_DSC)
257
          begin
258
             err_dsc <= 1'b1;  //if disconnect,pulse periodically
259
                  edcnt <= 0;
260
         end
261
             else
262
             edcnt <= edcnt + 1'b1;
263
      end
264
          end
265
 
266
always @(posedge gclk)
267
if(rst_edcnt)
268
  Lnk_dsc_o <= 0;          //Lnk_dsc_o is a lecel corresponds to the "err_dsc"
269
else if(err_dsc)
270
  Lnk_dsc_o <= 1;
271
 
272
///////////////////////////////////////////////
273
//Register the data pattern identificate result
274
//
275
always @(posedge gclk)
276
if(reset)
277
  { isNULL_1, isEOP_1, isEEP_1, isFCT_1, isDATA_1, isTIME_1 } <= 0;
278
else if(scover_pre)
279
   { isNULL_1, isEOP_1, isEEP_1, isFCT_1, isDATA_1, isTIME_1  }
280
<= { isNULL,   isEOP,   isEEP,   isFCT,   isDATA,   isTIME  };
281
 
282
///////////////////////////////////////////////
283
//Output Time and N_Char(data/EOP/EEP)
284
//
285
always @(posedge gclk)  //if Rec2CLK die,use system clk to write.
286
if(reset)
287
  {CtrlFlg_o,TIMEout,type_o} <= 0;
288
else if (CcTIME==True)
289
         begin
290
            CtrlFlg_o <= rereg[13:12];
291
            TIMEout <= rereg[11:6];
292
         end
293
else if (CcNchar==True)
294
        begin
295
                      wrtbuf_o <= wrtbuf_itl;
296
            case (1'b1) /* synthesis parallel_case */
297
             isDATA_1 :  begin
298
                                  type_o <= 0;  //flag == 0
299
                                  RxData_o <= rereg[9:2];
300
                                  end
301
             isEOP_1  :  begin
302
                                       type_o <= 1;
303
                                       RxData_o <= 8'b0000_0000;//flag==1 xxxxxxx0 (use 00000000) EOP
304
                                               end
305
             isEEP_1  : //remote EEP
306
                                       begin
307
                                       type_o <= 1;
308
                                       RxData_o <= 8'b0000_0001;//flag==1 xxxxxxx1 (use 00000001) EEP
309
                                       end
310
               default : begin
311
                                                    type_o <= 'bx;
312
                                                                        RxData_o <= 'bx;
313
                         end
314
             endcase
315
                 end
316
/////////////////////////
317
// control FSM
318
//
319
reg gotNULL_itl;  //a wire that has the value of gotNULL_o
320
always @(posedge gclk)
321
if(reset==`reset)
322
    begin
323
    state <= RESET;   //Initialized state
324
         gotNULL_o <= 1'b0;
325
         end
326
else
327
   begin
328
     state <= next_state;
329
 
330
     gotNULL_o <= gotNULL_itl; //register the gotNULL_itl
331
   end
332
//------ next_state assignment
333
always @(*)
334
begin:NEXT_ASSIGN
335
  //Default Values for FSM outputs:
336
    gotBIT_o  = 1'b0;
337
    gotTIME_o = 1'b0;
338
    gotFCT_o  = 1'b0;
339
    gotNchar_o = 1'b0;
340
    gotNULL_itl  = 1'b0;  //gotNULL_o is a level output
341
    TICK_OUT = 1'b0;
342
   // C_ParCheck = 1'b0;
343
    CcTIME = 1'b0;
344
    CcNchar = 1'b0;
345
    err_par = 1'b0;
346
         err_esc = 1'b0;
347
    wrtbuf_itl = 1'b0;
348
  //Use "Default next_state" style ->
349
    next_state = state;
350
      case(state)   /* synthesis parallel_case */
351
  RESET        :  begin
352
                    if(state_i==`ErrorWait)
353
                       next_state = HUNTING;
354
                  end
355
  HUNTING      :  begin  //Stay state. //common because the first parity bit is 0,so Si must jump high first
356
                    gotNULL_itl = gotNULL_o;  //keep a level
357
                    if(scover_pre)
358
                      begin
359
                        gotBIT_o = 1'b1;  //pulse 
360
                        next_state = CHECK_CHAR;
361
                      end
362
                  end
363
  CHECK_CHAR   :  begin //Temporary state 
364
                    if(par_ok)
365
                    begin
366
                       next_state = HUNTING;
367
                       if(isFCT_1)
368
                       gotFCT_o = 1;  //4 bit FCT                                                
369
                       else if(isNULL_1)   //8 bit NULL
370
                          begin
371
                          gotNULL_itl = 1'b1;   //gotNull is a level                           
372
                          end
373
                       else if( isEOP_1 || isEEP_1 || isDATA_1 )
374
                          begin
375
                                                                  gotNchar_o = 1;  // 10bit data or 4bit EOP/EEP (are all Nchar)                                               
376
                                                                  CcNchar = 1'b1;  //Command to collect Normal character
377
                                                                  if(state_i==`Run && !full_i)
378
                                                                  wrtbuf_itl = 1;
379
                          end
380
                       else if(isTIME_1)
381
                          begin
382
                          gotTIME_o = 1;  //inform the PPU
383
                                                                  CcTIME = 1'b1; //Command to collect Time
384
                          if(state==`Run)
385
                                                                  TICK_OUT = 1;
386
                          end
387
                       else if(isESC_ERR && state_i==`Connecting)
388
                                                             begin
389
                                                                    if(state_i==`Connecting || state_i==`Run) //after   the first NULL is received.
390
                                                                    begin
391
                                                                    err_esc = 1'b1;
392
                                                                    next_state = RESET;
393
                                                                    end
394
                                                                  end
395
                                                        end
396
                    else  //if the preliminary parity bit check is wrong                
397
                                                          if(state_i==`Connecting || state_i==`Run)
398
                                                          begin
399
                                                          err_par = 1'b1;       //Parity detection shall be enabled whenever the receiver is enabled after the first NULL is received.
400
//If the parity error occurs in the Run state then the parity error shall be flagged up to the  Network Level as a "link error"                      
401
                                                          next_state = RESET;
402
                                                          end
403
                    end
404
    default    :    next_state = DEFLT;
405
   endcase
406
end //end combinatorial block "NEXT_ASSIGN"
407
 
408
 
409
/*
410
function[RCVW-1:0] rcv_allocate;  //mux instead LSR
411
input din;
412
input [3:0] sel;
413
begin
414
   rcv_allocate =0;
415
  case(sel)
416
    4'd0  :  rcv_allocate[0] = din;
417
         4'd1  :  rcv_allocate[1] = din;
418
         4'd2  :  rcv_allocate[2] = din;
419
         4'd3  :  rcv_allocate[3] = din;
420
         4'd4  :  rcv_allocate[3] = din;
421
         4'd5  :  rcv_allocate[5] = din;
422
         4'd6  :  rcv_allocate[6] = din;
423
         4'd7  :  rcv_allocate[7] = din;
424
         4'd8  :  rcv_allocate[8] = din;
425
         4'd9  :  rcv_allocate[9] = din;
426
         4'd10 :  rcv_allocate[10] = din;
427
         4'd11 :  rcv_allocate[11] = din;
428
         4'd12  :  rcv_allocate[12] = din;
429
         4'd13  :  rcv_allocate[13] = din;
430
         default : rcv_allocate = 'bx;
431
  endcase
432
 
433
end
434
endfunction     */
435
 
436
//...................................................................................
437
 
438
endmodule
439
`undef ErrorReset
440
`undef ErrorWait
441
`undef Ready
442
`undef Started
443
`undef Connecting
444
`undef Run
445
`undef reset
446
`undef XIL_DEVICE

powered by: WebSVN 2.1.0

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