source: ResearchApps/PHY/MIMO_OFDM/SG10/fec_encoder.v

Last change on this file was 1820, checked in by murphpo, 12 years ago
File size: 21.2 KB
Line 
1//**********************************************************************************************
2// File:    fec_encoder.v
3// Author:  Yang Sun (ysun@rice.edu)
4// Created: 2010.10.8
5//**********************************************************************************************
6module fec_encoder (
7        clk             ,   // I, clock
8        ce              ,   // I, clock enable
9        nrst            ,   // I, n reset
10        start           ,   // I, start pulse
11        coding_en       ,   // I, coding enable
12        pkt_done        ,   // I, pkt transmit done
13        fec_rd          ,   // I, fec data request
14        info_data       ,   // I, info data
15        info_scram      ,   // I, info data scrabled
16        info_len        ,   // I, number of payload
17        codeword_len    ,   // O, number of coded data in bytes
18        info_rd         ,   // O, read
19        info_raddr      ,   // O, TX byte address
20        fec_data            // O, encoded data in bytes
21        ) ;
22       
23input           clk ;
24input           ce ;
25input           nrst ;
26input           start ;
27input           coding_en ;
28input           pkt_done ;
29input           fec_rd ;
30input   [7:0]   info_data ;
31input   [7:0]   info_scram ;
32input   [15:0]  info_len ;
33output  [15:0]  codeword_len ;
34output          info_rd ;
35output  [13:0]  info_raddr ;
36output  [7:0]   fec_data ;
37
38
39//============================
40//Internal signal
41//============================
42reg             in_enc ;
43wire            ff_half_full ;
44wire    [7:0]   ff_wdata ;
45wire            ff_wr ;
46wire            ff_rd ;
47wire    [7:0]   ff_rdata ;
48wire            enc_done ;
49wire            ffdata_req ;
50reg             ffdata_req_d ;
51reg             ffdata_req_dd ;
52reg     [13:0]  addr_out ;
53
54wire    [7:0]   sff_din_cc ;
55wire            sff_empty_cc ;
56wire            sff_full_cc ;
57wire            sff_rd_cc ;
58wire            sff_wr_cc ;
59wire    [3:0]   sff_dout_cc ;
60
61wire            cc_vin ;
62wire    [3:0]   cc_din ;
63wire    [7:0]   cc_dout ;
64wire    [7:0]   cc_mask ;
65wire    [7:0]   cc_dpunct ;
66wire    [3:0]   n_cc_dpunct ;
67
68wire            sff_empty_qam ;
69wire            sff_full_qam ;
70wire            sff_rd_qam ;
71wire            sff_wr_qam ;
72wire    [7:0]   sff_dout_qam ;
73wire    [7:0]   sff_din_qam ;
74wire    [3:0]   sff_nsin_qam ;
75wire            coding_en ;
76wire    [1:0]   cc_rate_mux ;
77reg     [1:0]   cc_rate ;
78
79reg     [5:0]   cc_cnt ;
80wire            in_baserate_cc ;
81reg     [7:0]   fec_data_i ;
82wire            bypass ;
83
84reg     [15:0]  pkt_len ;
85reg     [15:0]  info_len_lat ;
86reg     [15:0]  payload_len ;
87wire    [15:0]  payload_len_i ;
88
89wire    [10:0]  coe ;
90wire    [26:0]  tmp_mult ;
91reg     [15:0]  payload_coded ;
92
93//============================
94// Main RTL
95//============================
96assign info_raddr = addr_out ;
97assign fec_data = fec_data_i ;
98assign info_rd = ffdata_req_d ;
99assign codeword_len = pkt_len ;
100
101always @ (posedge clk or negedge nrst)
102  if(~nrst)
103    fec_data_i <= 0 ;
104  else if(ce)
105  begin
106    if(start)
107      fec_data_i <= 0 ;
108    else if(fec_rd)
109      fec_data_i <= sff_dout_qam ;
110  end
111
112
113always @ (posedge clk or negedge nrst)
114  if (~nrst)
115    in_enc <= 1'b0 ;
116  else if (ce)
117  begin
118    if (start)
119      in_enc <= 1'b1 ;
120    else if (pkt_done)
121      in_enc <= 1'b0 ;
122  end
123
124assign ffdata_req = in_enc & ~ff_half_full ;
125always @ (posedge clk or negedge nrst)
126  if (~nrst)
127    {ffdata_req_dd, ffdata_req_d} <= 2'b00 ;
128  else if (ce)
129    {ffdata_req_dd, ffdata_req_d} <= {ffdata_req_d, ffdata_req} ;
130
131always @ (posedge clk or negedge nrst)
132  if (~nrst)
133    addr_out <= 0 ;
134  else if (ce)
135  begin
136    if (start)
137      addr_out <= 0 ;
138    else if (ffdata_req)
139      addr_out <= addr_out +1 ;
140  end
141
142 
143assign ff_wr = ffdata_req_dd ;
144assign ff_wdata = info_scram ;
145assign ff_rd = sff_wr_cc ;
146
147//-- 8x8 Input FIFO
148fifo_async_rd #(8, 8, 3) input_fifo (
149    .clk        (clk            ),
150    .nrst       (nrst           ),
151    .ce         (ce             ),
152    .reset      (start          ),
153    .wdata      (ff_wdata       ),
154    .wr         (ff_wr          ),
155    .rd         (ff_rd          ),
156    .rdata      (ff_rdata       ),
157    .empty      (ff_empty       ),
158    .half_full  (ff_half_full   ),
159    .full       (ff_full        )
160    ) ;
161
162   
163assign sff_din_cc = ff_rdata ;   
164assign sff_wr_cc = (~sff_full_cc) & (~ff_empty) & in_enc ;
165assign sff_rd_cc = sff_wr_qam ;
166
167//-- shift fifo between input fifo and CC encoder
168sfifo_8to4 cc_fifo (
169        .clk        (clk            ),  // clock
170        .ce         (ce             ),  // clock enable
171        .nrst       (nrst           ),  // asyn reset
172        .reset      (start          ),  // sync reset
173        .din        (sff_din_cc     ),  // data input
174        .dout       (sff_dout_cc    ),  // data output
175        .rd         (sff_rd_cc      ),  // read
176        .wr         (sff_wr_cc      ),  // write
177        .full       (sff_full_cc    ),  // fifo full
178        .empty      (sff_empty_cc   ),  // fifo empty
179        .nsin       (4'd8           ),  // num of shift in (bits)
180        .nsout      (4'd4           )   // num of shift out (bits)
181        ) ;
182
183// get coding rate from second byte of the header
184always @ (posedge clk or negedge nrst)
185  if (~nrst)
186    cc_rate <= 0 ;
187  else if (ce)
188  begin
189    if(start)
190      cc_rate <= 0 ;
191    else if (info_rd & (info_raddr == 3))   // read latency is 2
192      cc_rate <= info_data ;
193  end
194
195assign cc_vin = sff_wr_qam  ;
196assign cc_din = sff_dout_cc ;
197assign cc_rate_mux = in_baserate_cc ? 0 : cc_rate ;
198
199//-- cc_encoder
200cc_encoder cc_encoder (
201        .clk        (clk            ),  // I, clock                                                                                             
202        .ce         (ce             ),  // I, clock enable                                                                                     
203        .nrst       (nrst           ),  // I, n reset                                                                                           
204        .cc_start   (start          ),  // I, start pulse           
205        .rate       (cc_rate_mux    ),  // I, code rate                                                                           
206        .vin        (cc_vin         ),  // I, valid in                                                                                         
207        .din        (cc_din         ),  // I, parallel data input. QPSK = din[3], 16-QAM = din[3:2], 64-QAM = din[3:1], 256-QAM = din[3:0]     
208        .vout       (               ),  // O, encoded data out valid                                                                           
209        .dout       (cc_dout        ),  // O, arallel data output. QPSK = dout[7:6], 16-QAM = dout[7:4], 64-QAM = dout[7:2], 256-QAM = dout[7:0]
210        .mask       (cc_mask        )   // O, mask
211        ) ;
212
213always @ (posedge clk or negedge nrst)
214  if (~nrst)
215    cc_cnt <= 0 ;
216  else if (ce)
217  begin
218    if(start)
219      cc_cnt <= 0 ;
220    else if (cc_vin & in_baserate_cc)
221      cc_cnt <= cc_cnt +1 ;
222  end
223 
224assign in_baserate_cc = cc_cnt != 48; 
225
226//-- cc_puncture
227cc_puncture cc_puncture (
228    .din    (cc_dout    )   ,   // I, data in
229    .mask   (cc_mask    )   ,   // I, data in mask
230    .dout   (cc_dpunct  )   ,   // O, data out
231    .ndout  (n_cc_dpunct)       // O, number of output bits
232    ) ;
233
234assign sff_rd_qam = fec_rd ;
235assign sff_wr_qam = ((~sff_full_qam) & (~sff_empty_cc)) & in_enc ;
236
237assign bypass = (~coding_en) | (cc_rate_mux == 3) ;
238assign sff_din_qam = bypass ? {sff_dout_cc, 4'd0} : cc_dpunct ;
239assign sff_nsin_qam = bypass ? 4 : n_cc_dpunct ;
240
241//-- shift fifo between cc encoder and QAM modulator
242sfifo_nto8 output_fifo (
243        .clk        (clk            ),  // clock
244        .ce         (ce             ),  // clock enable
245        .nrst       (nrst           ),  // asyn reset
246        .reset      (start          ),  // sync reset
247        .din        (sff_din_qam    ),  // data input
248        .dout       (sff_dout_qam   ),  // data output
249        .rd         (sff_rd_qam     ),  // read
250        .wr         (sff_wr_qam     ),  // write
251        .full       (sff_full_qam   ),  // fifo full
252        .empty      (sff_empty_qam  ),  // fifo empty
253        .nsin       (sff_nsin_qam   ),  // num of shift in (bits), could be 4, 6 or 8       
254        .nsout      (4'd8           )   // num of shift out (bits)
255        ) ;
256
257
258always @(posedge clk or negedge nrst)
259  if(~nrst)
260    info_len_lat <= 256 ;
261  else if(ce)
262    info_len_lat <= info_len ;
263
264always @(posedge clk or negedge nrst)
265  if(~nrst)
266    payload_len <= 0 ;
267  else if(ce)
268    payload_len <= info_len -24 ;
269
270assign payload_len_i = {payload_len, 1'b0} ;
271
272wire [5:0] lenAdj;
273assign lenAdj = (info_len == 24) ? 48 : 50;
274
275always @*
276begin
277  pkt_len = info_len_lat ;
278  if(coding_en)
279  begin
280    case(cc_rate_mux)
281      2'd0: pkt_len = {info_len_lat[14:0], 1'b0} ;  // rate 1/2
282      2'd1: pkt_len = payload_coded +lenAdj ;           // rate 2/3
283      2'd2: pkt_len = payload_coded +lenAdj ;           // rate 3/4
284//      2'd1: pkt_len = payload_coded +50 ;           // rate 2/3
285//      2'd2: pkt_len = payload_coded +50 ;           // rate 3/4
286      2'd3: pkt_len = info_len_lat +24 ;            // rate 1
287    endcase
288  end   
289  else
290    pkt_len = info_len_lat ;
291end
292
293// 1536 = 3/4 * 2048, 1365 = 2/3 * 2048
294assign coe = (cc_rate_mux == 1) ? 1536 : 1365 ;   
295assign tmp_mult = coe * payload_len_i ;
296
297always @(posedge clk or negedge nrst)
298  if(~nrst)
299    payload_coded <= 256 ;
300  else if (ce)
301    payload_coded <= tmp_mult[26:11] ;
302   
303endmodule
304
305//**************************************************************
306// File:    cc_encoder.v
307// Author:  Yang Sun (ysun@rice.edu)
308// Created: $ 02/11/07
309// Des:     Convolutional encoder core
310//          K = 7, compliant with 802.11a
311// u0 u1 u2 u3 -> {A0,B0}, {A1,B1}, {A2,B2}, {A3,B3}
312//
313// History: $ 02/11/07, First version, K = 5
314//          $ 03/31/07, Added 256-QAM
315//          $ 04/20/07, K = 7
316//          $ 04/29/07, Added ce
317//          $ 11/26/07, Remove puncture
318//          $ 09/27/08, Added puncture
319//          $ 10/11/08, Added uncoded and BPSK support
320//**************************************************************
321module cc_encoder (
322        clk         ,   // I, clock
323        ce          ,   // I, clock enable
324        nrst        ,   // I, n reset
325        cc_start    ,   // I, start pulse
326        rate        ,   // I, code rate, 0 = 1/2, 1 = 2/3, 2 = 3/4
327        vin         ,   // I, valid in
328        din         ,   // I, parallel data input [3:0]
329        vout        ,   // O, encoded data out valid
330        dout        ,   // O, Parallel data output [7:0]
331        mask            // O, mask
332        ) ;
333       
334input               clk ;
335input               ce ;
336input               nrst ;
337input               cc_start ; 
338input       [1:0]   rate ;
339input               vin ;       
340input       [3:0]   din ;       
341output              vout ;     
342output      [7:0]   dout ;
343output reg  [7:0]   mask ;
344
345//===========================================
346//Internal signal
347//===========================================
348wire    [3:0]   u ;
349wire    [7:0]   v ;
350
351reg             s0 ;
352reg             s1 ;
353reg             s2 ;
354reg             s3 ;
355reg             s4 ;
356reg             s5 ;
357
358wire            s0_next ;
359wire            s1_next ;
360wire            s2_next ;
361wire            s3_next ;
362wire            s4_next ;
363wire            s5_next ;
364
365wire    [3:0]   A ;
366wire    [3:0]   B ;
367
368reg     [1:0]   cnt ;
369
370//===========================================
371// Main body of code
372//===========================================
373assign vout = vin ;
374assign dout = v ;
375
376assign A[3] = u[3] ^ s1 ^ s2 ^ s4 ^ s5 ;
377assign B[3] = u[3] ^ s0 ^ s1 ^ s2 ^ s5 ;
378
379assign A[2] = (u[2] ^ s0 ^ s1 ^ s3 ^ s4) ;
380assign B[2] = (u[2] ^ u[3] ^ s0 ^ s1 ^ s4) ;
381
382assign A[1] = (u[1] ^ u[3] ^ s0 ^ s2 ^ s3) ;
383assign B[1] = (u[1] ^ u[2] ^ u[3] ^ s0 ^ s3) ;
384
385assign A[0] = (u[0] ^ u[2] ^ u[3] ^ s1 ^ s2) ;
386assign B[0] = (u[0] ^ u[1] ^ u[2] ^ u[3] ^ s2) ;
387
388assign u = din ;
389assign v = {A[3], B[3], A[2], B[2], A[1], B[1], A[0], B[0]} ;
390
391assign s0_next = u[0] ;
392assign s1_next = u[1] ;
393assign s2_next = u[2] ;
394assign s3_next = u[3] ;
395assign s4_next = s0 ;
396assign s5_next = s1 ;
397
398always @ (posedge clk or negedge nrst)
399  if (~nrst)
400  begin
401    s0 <= 1'b0 ;
402    s1 <= 1'b0 ;
403    s2 <= 1'b0 ;
404    s3 <= 1'b0 ;
405    s4 <= 1'b0 ;
406    s5 <= 1'b0 ;
407  end
408  else if (ce)
409  begin
410    if (cc_start)
411    begin
412      s0 <= 1'b0 ;
413      s1 <= 1'b0 ;
414      s2 <= 1'b0 ;
415      s3 <= 1'b0 ;
416      s4 <= 1'b0 ;
417      s5 <= 1'b0 ;
418    end
419    else if (vin)
420    begin
421      s0 <= s0_next ;
422      s1 <= s1_next ;
423      s2 <= s2_next ;
424      s3 <= s3_next ;
425      s4 <= s4_next ;
426      s5 <= s5_next ;
427    end
428  end
429
430always @ (posedge clk or negedge nrst)
431  if (~nrst)
432    cnt <= 0 ;
433  else if (ce)
434  begin
435    if (cc_start)
436      cnt <= 0 ;
437    else if (vin)
438    begin
439      if (cnt == 2)
440        cnt <= 0 ;
441      else
442        cnt <= cnt +1 ;
443    end
444  end
445
446always @*
447begin
448  mask = 8'd0 ;
449  if (rate == 0)
450    mask = 8'b1111_1111 ;
451  else if (rate == 1)
452    mask = 8'b1110_1110 ;
453  else
454  begin
455    case(cnt)
456      0: mask = 8'b1110_0111 ;
457      1: mask = 8'b1001_1110 ; 
458      2: mask = 8'b0111_1001 ;
459      default: mask = 8'b1110_0111 ;
460    endcase
461  end
462end
463
464endmodule
465
466
467//**************************************************************
468// File:    cc_puncture.v
469// Author:  Yang Sun (ysun@rice.edu)
470// Created: $ 09/27/08
471// Des:     data puncture
472//
473// History: $ 09/27/08, created
474//**************************************************************
475module cc_puncture (
476    din         ,   // I, data in
477    mask        ,   // I, data in mask
478    dout        ,   // O, data out
479    ndout           // O, number of output bits
480    ) ;
481   
482input       [7:0]   din ;
483input       [7:0]   mask ;
484
485output reg  [7:0]   dout ;
486output reg  [3:0]   ndout ;
487
488//===========================================
489//Internal signal
490//===========================================
491
492
493//===========================================
494// Main RTL
495//===========================================
496always @*
497begin
498  ndout = 8 ;
499  dout = din ;
500 
501  case (mask)   
502    8'b1111_1111: begin // rate 1/2
503      ndout = 8 ;
504      dout = din ;
505    end
506    8'b1110_1110: begin // rate 2/3
507      ndout = 6 ;
508      dout = {din[7:5], din[3:1], 1'b0, 1'b0} ;
509    end
510    8'b1110_0111: begin // rate 3/4
511      ndout = 6 ;
512      dout = {din[7:5], din[2:0], 1'b0, 1'b0} ;
513    end   
514    8'b1001_1110: begin // rate 3/4
515      ndout = 5 ;
516      dout = {din[7], din[4:1], 1'b0, 1'b0, 1'b0} ;
517    end 
518    8'b0111_1001: begin // rate 3/4
519      ndout = 5 ;
520      dout = {din[6:3], din[0], 1'b0, 1'b0, 1'b0} ;
521    end         
522  endcase 
523end
524
525endmodule
526
527//*********************************************************
528// File:    my_fifo_a.v
529// Author:  Y. Sun
530// Des:     Asnyc read FIFO
531//*********************************************************
532module fifo_async_rd (
533    clk         ,   // I, clock
534    ce          ,   // I, clock en
535    nrst        ,   // I, async reset
536    reset       ,   // I, sync reset
537    wdata       ,   // I, write data
538    wr          ,   // I, write enable
539    rd          ,   // I, read enable
540    rdata       ,   // I, read data
541    empty       ,   // O, empty
542    half_full   ,   // O, half full
543    full            // O, full
544    ) ;
545
546parameter           WIDTH = 8 ;
547parameter           DEPTH = 8 ;
548parameter           ADDR_BITS = 3 ;
549
550input               clk ;
551input               ce ;
552input               nrst ;
553input               reset ;
554input   [WIDTH-1:0] wdata ;
555input               wr ;
556input               rd ;
557output  [WIDTH-1:0] rdata ;
558output              empty ;
559output              half_full ;
560output              full ;
561
562
563//============================
564// Internal signals
565//============================
566reg     [WIDTH-1:0]     mem [DEPTH-1:0] ;
567reg     [ADDR_BITS:0]   cnt ;
568reg     [ADDR_BITS-1:0] waddr ;
569reg     [ADDR_BITS-1:0] raddr ;
570
571//============================
572// Main RTL Code
573//============================
574assign empty = cnt == 0 ;
575assign full = cnt == DEPTH ;
576assign half_full = cnt >= DEPTH/2 ;
577
578
579always @ (posedge clk or negedge nrst)
580  if(~nrst)
581    cnt <= 0 ; 
582  else if(ce)
583  begin
584    if (reset)
585      cnt <= 0 ;
586    else if (wr & ~rd)
587      cnt <= cnt +1 ;
588    else if (rd & ~wr)
589      cnt <= cnt -1 ;
590  end
591
592always @ (posedge clk or negedge nrst)
593  if(~nrst)
594    waddr <= 0 ;
595  else if(ce)
596  begin
597    if (reset)
598      waddr <= 0 ;
599    else if (wr)
600      waddr <= waddr == DEPTH -1 ? 0 : waddr +1 ;
601  end
602   
603always @ (posedge clk or negedge nrst)
604  if(~nrst)
605    raddr <= 0 ;
606  else if(ce)
607  begin
608    if (reset)
609      raddr <= 0 ;
610    else if (rd)
611      raddr <= raddr == DEPTH -1 ? 0 : raddr +1 ;   
612  end 
613
614always @ (posedge clk)
615  if(ce)
616  begin
617    if (wr)
618      mem [waddr] <= wdata ;
619  end
620
621assign rdata = mem [raddr] ;
622
623endmodule
624
625//********************************************************************************
626// File:    sfifo_8to4
627// Author:  Yang Sun (ysun@rice.edu)
628// Birth:   $ 11/24/07
629// Des:     Small size serial fifo
630// History: $ 11/24/07, Created
631//          $ 11/26/07, Modify input format
632//********************************************************************************
633module sfifo_8to4 (
634        clk         ,   // clock
635        ce          ,   // clock enable
636        nrst        ,   // asyn reset
637        reset       ,   // sync reset
638        din         ,   // data input
639        dout        ,   // data output
640        rd          ,   // read
641        wr          ,   // write
642        full        ,   // fifo full
643        empty       ,   // fifo empty
644        nsin        ,   // num of shift in (bits), could be 4, 6 or 8
645        nsout           // num of shift out (bits), could be 2 or 4.
646        ) ;
647       
648input           clk ;
649input           ce ;
650input           nrst ;
651input           reset ;
652input   [7:0]   din ;
653output  [3:0]   dout ;
654input           rd ;
655input           wr ;
656output          full ;
657output          empty ;
658input   [3:0]   nsin ;
659input   [3:0]   nsout ;
660
661//=========================
662// Internal signal
663//=========================
664reg     [15:0]  buffer ;
665reg     [4:0]   cnt ;
666wire    [19:0]  shift_out ;
667wire    [23:0]  shift_in ;
668wire    [4:0]   space_left ;
669
670//=========================
671// Main RTL
672//=========================
673assign full = (cnt + nsin) > 16 ;
674assign empty = cnt < nsout ;
675
676always @ (posedge clk or negedge nrst)
677  if (~nrst)
678    cnt <= 0 ;
679  else if (ce)
680  begin
681    if (reset)
682      cnt <= 0 ;
683    else
684    begin
685      if (wr & rd)
686        cnt <= cnt +nsin -nsout ;
687      if (wr & ~rd)
688        cnt <= cnt +nsin ;
689      if (~wr & rd)
690        cnt <= cnt -nsout ;
691    end
692  end
693 
694assign shift_out = {4'h0, buffer} << nsout ; 
695assign dout = shift_out [19:16] ; 
696 
697assign space_left = rd ? 16 -cnt + nsout : 16 -cnt ; 
698assign shift_in = {16'h0, din} << space_left ;
699 
700always @ (posedge clk or negedge nrst)
701  if (~nrst)
702    buffer <= 0 ;
703  else if (ce)
704  begin
705    if (reset)
706      buffer <= 0 ;
707    else
708    begin
709      if (wr & rd)
710        buffer <= shift_out [15:0] | shift_in [23:8] ;
711      if (wr & ~rd)
712        buffer <= buffer | shift_in [23:8] ;
713      if (~wr & rd)
714        buffer <= shift_out [15:0] ;
715    end
716  end 
717
718endmodule
719
720//********************************************************************************
721// File:    sfifo_8to8
722// Author:  Yang Sun (ysun@rice.edu)
723// Des:     Small size serial fifo, n bit in, 8 bit out
724//********************************************************************************
725module sfifo_nto8 (
726        clk         ,   // clock
727        ce          ,   // clock enable
728        nrst        ,   // asyn reset
729        reset       ,   // sync reset
730        din         ,   // data input
731        dout        ,   // data output
732        rd          ,   // read
733        wr          ,   // write
734        full        ,   // fifo full
735        empty       ,   // fifo empty
736        nsin        ,   // num of shift in (bits)
737        nsout           // num of shift out (bits)
738        ) ;
739       
740input           clk ;
741input           ce ;
742input           nrst ;
743input           reset ;
744input   [7:0]   din ;
745output  [7:0]   dout ;
746input           rd ;
747input           wr ;
748output          full ;
749output          empty ;
750input   [3:0]   nsin ;
751input   [3:0]   nsout ;
752
753//=========================================
754// Internal signal
755//=========================================
756reg     [23:0]  buffer ;        // 24-bit buffer
757reg     [5:0]   cnt ;           // counter to record num of bits loaded into buffer
758wire    [31:0]  shift_out ;
759wire    [31:0]  shift_in ;
760wire    [5:0]   space_left ;
761
762//=========================================
763// Main RTL
764//=========================================
765assign dout = shift_out [31:24] ;
766assign full = (cnt + nsin) > 24 ;
767assign empty = cnt < nsout ;
768
769always @ (posedge clk or negedge nrst)
770  if (~nrst)
771    cnt <= 0 ;
772  else if (ce)
773  begin
774    if (reset)
775      cnt <= 0 ;
776    else
777    begin
778      if (wr & rd)
779        cnt <= cnt + nsin - nsout ;
780      if (wr & ~rd)
781        cnt <= cnt + nsin ;
782      if (~wr & rd)
783        cnt <= cnt - nsout ;
784    end
785  end
786 
787assign shift_out = {8'h0, buffer} << nsout ; 
788assign space_left = rd ? 24 -cnt + nsout : 24 -cnt ; 
789assign shift_in = {24'h0, din} << space_left ;
790 
791always @ (posedge clk or negedge nrst)
792  if (~nrst)
793    buffer <= 0 ;
794  else if (ce)
795  begin
796    if (reset)
797      buffer <= 0 ;
798    else
799    begin
800      if (wr & rd)
801        buffer <= shift_out [23:0] | shift_in [31:8] ;
802      if (wr & ~rd)
803        buffer <= buffer | shift_in [31:8] ;
804      if (~wr & rd)
805        buffer <= shift_out [23:0] ;
806    end
807  end 
808
809endmodule
Note: See TracBrowser for help on using the repository browser.