这几天在研究FPGA的乒乓操作,乒乓操作的理论很多参考书、网上的资料都有讲解,这里我就不啰嗦了,我想分四个部分来研究乒乓操作:
一、用寄存器做缓存,一次可以缓存N bit的数据
二、用FPGA内部RAM做缓存,要用到两块RAM
三、用FPGA内部的真正的双口RAM做缓存,用一块双口RAM即可
四、用外部的两块SRAM做缓存
先给出第一部分的设计内容,其余的将在后面给出,欢迎大家指教,谢谢
设计源码:
module pingpang( clk ,
rst_n ,
data_in , //输入数据
data_out //输出数据
);
input clk ;
input rst_n ;
input [7:0] data_in ;
output [7:0] data_out;
reg [7:0] data_out;
reg [7:0] buffer1 ; //缓存1
reg [7:0] buffer2 ; //缓存2
reg wr_flag ; //写标志, wr_flag = 0,写buffer1,wr_flag = 1,写buffer2
reg rd_flag ; //读标志, rd_flag = 0,读buffer2,wr_flag = 1,读buffer1
reg state ; //状态机, 0:写1读2, 1:写2读1 ,状态转移和输出分开编码
always @ (posedge clk or negedge rst_n) //状态转移
begin
if(rst_n == 1'b0) state <= 1'b0;
else
begin
case(state)
1'b0 : state <= 1'b1;
1'b1 : state <= 1'b0;
default : state <= 1'b0;
endcase
end
end
always @ (state ) //状态输出
begin
case(state)
1'b0 : begin
wr_flag = 1'b0; //写1
rd_flag = 1'b0; //读2
end
1'b1 : begin
wr_flag = 1'b1; //写2
rd_flag = 1'b1; //读1
end
default : begin
wr_flag = 1'b0;
rd_flag = 1'b0;
end
endcase
end
always @ (posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
buffer1 <= 8'b0;
buffer2 <= 8'b0;
end
else
begin
case(wr_flag)
1'b0 : buffer1 <= data_in; //wr_flag = 0 ,写buffer1
2'b1 : buffer2 <= data_in; //wr_flag = 1 ,写buffer2
default : begin
buffer1 <= 8'b0;
buffer2 <= 8'b0;
end
endcase
end
end
always @ (posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0) data_out <= 8'b0;
else
begin
case(rd_flag)
1'b0 : data_out <= buffer2; //rd_flag = 0,读buffer2
1'b1 : data_out <= buffer1; //rd_flag = 1,读buffer1
default : data_out <= 8'b0 ;
endcase
end
end
endmodule
test bench:
module pingpang_tb_v;
// Inputs
reg clk ;
reg rst_n ;
reg [7:0] data_in;
// Outputs
wire [7:0] data_out;
// Instantiate the Unit Under Test (UUT)
pingpang uut (
.clk (clk ),
.rst_n (rst_n ),
.data_in (data_in ),
.data_out(data_out)
);
initial
begin
// Initialize Inputs
clk = 0;
rst_n = 0;
data_in = 0;
#100;
rst_n = 1;
end
always #10 clk = ~clk;
always @ (posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0) data_in <= 8'b0;
else data_in <= data_in + 1'b1;
end
endmodule
RTL试图:
仿真图:
从仿真波形图可以看出,乒乓操作实现了数据的无缝连接。我的程序首先执行的是写1读2,怎么验证第一个数据是从2出来的啊,大家可以想一想,其实比较简单:
always @ (posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
buffer1 <= 8'b0;
buffer2 <= 8'b0;
end
else
begin
case(wr_flag)
1'b0 : buffer1 <= data_in; //wr_flag = 0 ,写buffer1
2'b1 : buffer2 <= data_in; //wr_flag = 1 ,写buffer2
default : begin
buffer1 <= 8'b0;
buffer2 <= 8'b0;
end
endcase
end
end
将上面程序中复位时buffer2的值,变成其他的值就可以了,然后在仿真就可以看到第一个数是从buffer2中读出,大家可以去试试,我已经试过了
用户218240 2011-1-6 15:14
用户1626244 2010-3-22 11:22