FPGA之乒乓操作


1.乒乓操作原理
  乒乓操作是一個主要用於數據流控制的處理技巧,典型的乒乓操作如圖所示:
  外部輸入數據流通過“輸入數據選擇控制”模塊送入兩個數據緩沖區中,數據緩沖模塊可以為任何存儲模塊,比較常用的存儲單元為雙口RAM(Dual RAM),SRAM,SDRAM,FIFO等。
 
       在第1個緩沖周期,將輸入的數據流緩存到“數據緩沖1”模塊,在第2個緩沖周期,“輸入數據選擇控制”模塊將輸入的數據流緩存到“數據緩沖2”模塊的同時,“輸出數據選擇控制”模塊將“數據緩沖1”模塊第一個周期緩存的數據流送到“后續處理”,模塊進行后續的數據處理,在第三個緩沖周期,在“輸入數據選擇控制”模塊的再次切換后,輸入的數據流緩存到“數據緩沖1”模塊,與此同時,“輸出數據選擇控制”模塊也做出切換,將“數據緩沖2”模塊緩存的第二個周期的數據送到“后續處理模塊”,如此循環。
  這里正是利用了乒乓操作完成數據的無縫緩沖與處理,乒乓操作可以通過“輸入數據選擇控制”和“輸出數據選擇控制”按節拍,相互配合地進行來回切換,將經過緩沖的數據流沒有停頓的送到“后續處理模塊”。

 

  比如將乒乓操作運用在液晶顯示的控制模塊上,如圖所示。

  對於外部接口傳輸的圖像數據,以一幀圖像為單位進行SDRAM的切換控制,當SDRAM1緩存圖像數據時,液晶顯示的是SDRAM2的數據圖像;反之,當SDRAM2緩存圖像數據時,液晶顯示的是SDRAM1的數據圖像,如此反復,這樣出路的好處在於液晶顯示圖像切換瞬間完成,掩蓋了可能比較緩慢的圖像數據流變換過程。
2.FPGA乒乓操作代碼
2.1 FPGA設計代碼
 1 module pingpang
 2     (
 3         input            clk        ,
 4         input            rst_n      ,
 5         input      [7:0] data_in    ,    // 輸入數據
 6         output reg [7:0] data_out        // 輸出數據
 7     );
 8     
 9 // ------------------------------------------------------ //
10     reg [7:0]    buffer1    ;    // 緩存1
11     reg [7:0]    buffer2    ;    // 緩存2
12     reg          wr_flag    ;    // 寫標志,wr_flag=0,寫buffer1,wr_flag=1,寫buffer2
13     reg          rd_flag    ;    // 讀標志,rd_flag=0,讀buffer2,rd_flag=1,讀buffer1
14     reg          state      ;    // 狀態機,0:寫1讀2,1:寫2讀1,狀態轉移和輸出分開編碼
15 // ------------------------------------------------------ //    
16     // 狀態轉移
17     always @ (posedge clk or negedge rst_n)
18     begin
19         if(rst_n == 1'b0)
20         begin
21             state <= 'b0;
22         end
23         else
24         begin
25             state <= !state;
26             //case(state)
27             //    1'b0    : state <= 1'b0;    // 寫1讀2->寫2讀1
28             //    1'b1    : state <= 1'b1;    // 寫2讀1->寫1讀2
29             //    default : state <= 1'b0;
30             //endcase
31         end
32     end
33 // ------------------------------------------------------ // 
34     // 狀態輸出
35     always @ (state)
36     begin
37         case(state)
38             1'b0:
39             begin
40                 wr_flag = 1'b0; // 寫1
41                 rd_flag = 1'b0; // 讀2
42             end
43             1'b1:
44             begin
45                 wr_flag = 1'b1; // 寫2
46                 rd_flag = 1'b1; // 讀1
47             end
48             default:
49             begin
50                 wr_flag = 1'b0;
51                 rd_flag = 1'b0;
52             end
53         endcase
54     end
55 // ------------------------------------------------------ //  
56     // 寫buffer數據   
57     always @ (posedge clk or negedge rst_n)
58     begin
59         if(rst_n == 1'b0)
60         begin
61             buffer1 <= 8'b0;
62             buffer2 <= 8'b0;
63         end
64         else
65         begin
66             case(wr_flag)
67                 1'b0    : buffer1 <= data_in;  // wr_flag = 0,寫buffer1
68                 1'b1    : buffer2 <= data_in;  // wr_flag = 1,寫buffer2
69                 default    :
70                 begin
71                     buffer1 <= 8'b0;
72                     buffer2 <= 8'b0;
73                 end
74             endcase
75         end
76     end    
77 // ------------------------------------------------------ // 
78     // 讀buffer數據
79     always @ (posedge clk or negedge rst_n)
80     begin
81         if(rst_n == 1'b0)
82         begin
83             data_out <= 8'b0;
84         end
85         else
86         begin
87             case(rd_flag)
88                 1'b0    : data_out <= buffer2;   // rd_flag=0,讀buffer2
89                 1'b1    : data_out <= buffer1;   // rd_flag=1,讀buffer1
90                 default : data_out <= 8'b0;
91             endcase
92         end
93     end
94 // ------------------------------------------------------ //     
95 endmodule

 

2.2 FPGA仿真代碼

`timescale 1ns / 1ps

module pingpang_tb();

    reg            clk        ;
    reg            rst_n    ;    
    reg    [7:0]    data_in    ;
    
    wire[7:0]    data_out;    
    
    always #10 clk = ~clk;
    
    initial
    begin
        rst_n    <= 1'b0    ;
        clk        <= 1'b0    ;
        #2010;
        rst_n    <= 1'b1    ;
    end
    
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            data_in    <= 'd0;
        else
            data_in    <= data_in + 1'b1;
    end
    
    pingpang dut
    (
        .clk            (clk        ),
        .rst_n            (rst_n        ),
        .data_in        (data_in    ),
                     
        .data_out        (data_out    )
    );
    
endmodule

 

3.仿真結果

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM