双fifo流水线实现3x1024数组数据按列相加

Vivado版本:2019.2 MATLAB Modelsim版本:Modelsim SE-64 10.7
实验内容:双fifo流水线实现3x1024数组数据按列相加

FIFO,First Input First Output,既先入先出,也是一种存储器。本质上还是RAM,外面加了一层地址管理,这样使得FIFO没有地址线,使得使用起来非常方便。缺点是只能顺序写入和顺序读出,不能随机访问。如果数据把FIFO写满了,数据就不能继续写入,原来的数据也不会被覆盖;读取数据也只能读取一遍,读空后继续进行读操作,数据会一直保持最后一个读出的数据。
通过官方指导手册查看时序细节以及IP核配置内容。
打开vivado软件,新建一个工程,配置芯片为xc7z020clg400-1:
在这里插入图片描述
进入工程,选择IP Catalog:在这里插入图片描述
在IP Catalog界面搜索框中输入FIFO,可以看到有多种接口的FIFO,如AXI接口和AXI_Stream接口,这里选择FIFO Generator:在这里插入图片描述
双击打开配置FIFO界面,左侧可以看到配置内容对应的接口,有FIFO读写使能信号、读写数据接口、空满信号以及时钟和复位,右侧可以配置模块的接口类型,以及时钟结构,可选的有Common Clock(读写同步时钟)与Independent Clocks(读写异步时钟)以及选用的存储类型,并且在下方表中可以查看各个存储类型支持的功能。
这里接口保持默认为Native,FIFO配置为Common Clock Block RAM:
在这里插入图片描述
FIFO读模式有两种,Standard FIFO与First Word Fall Through,Standard模式是相对于读使能,输出数据有1拍延时;FWFT模式特点是相对读使能可以0延时读出数据。
各自对应的时序为:
在这里插入图片描述
上图虽然是Independent Clock,但是读取时序与Common Clock一致。由上图所示,Standard模式下拉高rd_en读使能信号后,rd_clk下一拍时钟的上升沿数据线才会出数据,empty读空信号会在最后一个数据被读取时一同拉高,almost_empty在倒数第二个数据被读取时拉高。在这里插入图片描述
由上图所示,在First Word Fall Through模式下,第一个数据被提前放在dout线上,拉高rd_en后,并不需要等待一拍,empty信号也是在最后一个数据被读完时才拉高,almost_empty信号在读取最后一个数据时拉高。
再来看一下写的关键时序:写入并没有模式限制,在wr_en信号为高时,数据有效,在wr_clk作用下依次写入FIFO中,当fifo写满时,full满信号拉高。
在这里插入图片描述
在Native Ports标签下配置读模式为First Word Fall Through模式,写入位宽为16位,写入深度为1024,读取位宽为16位,读取深度自动生成为1024,ECC与输出寄存器不勾选,复位接口也不需要,该复位是复位一下接口,并不会清空FIFO中的内容,如果想清空fifo,可以使用读空的方式。在这里插入图片描述
Status Flags标签页下配置状态接口,默认接口中已经有空满信号,这些按设计添加。在这里插入图片描述
Data Counts配置数据计数器,Common Clock下读和写使用一个Data Count,如果是独立时钟,读和写就可以使用各自时钟域对应的计数器。通过官方手册得到,计数器会比读写使能延迟两个时钟。在这里插入图片描述
Summary标签显示配置的内容:在这里插入图片描述
注意:如果读写位宽不匹配,如写入读出比例为1:4,数据会先放在高位后放在低位,此时需要连续写入4拍,读出只需要1拍时钟。如图:在这里插入图片描述
写入与读出比例为4:1,则会先读出高位数据,后读出低位数据,此时写入一拍数据,读出需要4拍才能完全读完。如图:在这里插入图片描述
了解了FIFO的工作时序与配置内容,生成IP核,通过调用两次方式组装流水线。
目的是将3行1024列数组按列相加,数据是一行一行输入的,通过fifo1进行缓存,当缓存完1行数据后,开始读,读取的数据送入fifo2中进行缓存;当fifo2缓存完1行数据时,输入数据为第3行的第1列数据,fifo1中数据为第2行数据,fifo2中为第1行数据,如此就将连续输入的三行数据分离,然后逐列相加即可。时序如下:
在这里插入图片描述
按照时序图编写控制代码。并编写一个仿真激励,使用随机数据作为输入,验证流水线是否正常工作。
仿真结果如下:
在这里插入图片描述
可以看到在输入第三行数据(row=2)时,加法器启动,输出三行逐列相加的结果,时序与设计一致。
查看累加结果,也是正确的。
在这里插入图片描述
实验完成。

附:控制器代码:

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/06/04 11:19:25
// Design Name:
// Module Name: top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//

module top(
input wire sclk,
input wire rst_n,
input wire in_valid,
input wire [15:0] in_data,
output reg out_valid,
output reg [15:0] out_data
);

//---------------------------------------------------------------
// Define Signal
//---------------------------------------------------------------
reg [11:0] cnt_fifo_wr = 0;
wire [ 1:0] row;
wire [ 9:0] col;

wire fifo1_wr_en;
wire [15:0] fifo1_wr_data;
reg fifo1_rd_en;
wire [15:0] fifo1_rd_data;
wire fifo1_full;
wire fifo1_empty;
wire [10:0] fifo1_data_count;

wire fifo2_wr_en;
wire [15:0] fifo2_wr_data;
reg fifo2_rd_en;
wire [15:0] fifo2_rd_data;
wire fifo2_full;
wire fifo2_empty;
wire [10:0] fifo2_data_count;

reg [15:0] sum = 0;

//---------------------------------------------------------------
// Main Program
//---------------------------------------------------------------
always @(posedge sclk) begin
if (rst_n == 1’b0) begin // reset
cnt_fifo_wr <= 0;
end
else if (in_valid == 1’b1) begin
cnt_fifo_wr <= cnt_fifo_wr + 1;
end
else begin
cnt_fifo_wr <= 0;
end
end
assign row = cnt_fifo_wr[11:10];
assign col = cnt_fifo_wr[9:0];

assign fifo1_wr_en = in_valid;
assign fifo1_wr_data = in_data;
fifo_generator_0 fifo1 (
.clk (sclk ), // input wire clk
.din (fifo1_wr_data ), // input wire [15 : 0] din
.wr_en (fifo1_wr_en ), // input wire wr_en
.rd_en (fifo1_rd_en ), // input wire rd_en
.dout (fifo1_rd_data ), // output wire [15 : 0] dout
.full (fifo1_full ), // output wire full
.empty (fifo1_empty ), // output wire empty
.data_count (fifo1_data_count ) // output wire [10 : 0] data_count
);

always @(posedge sclk) begin
if (rst_n == 1’b0) begin // reset
fifo1_rd_en <= 0;
end
else if (fifo1_empty == 1’b1) begin
fifo1_rd_en <= 0;
end
else if (cnt_fifo_wr == 12’d1023) begin
fifo1_rd_en <= 1;
end
end

assign fifo2_wr_en = fifo1_rd_en;
assign fifo2_wr_data = fifo1_rd_data;
fifo_generator_0 fifo2 (
.clk (sclk ), // input wire clk
.din (fifo2_wr_data ), // input wire [15 : 0] din
.wr_en (fifo2_wr_en ), // input wire wr_en
.rd_en (fifo2_rd_en ), // input wire rd_en
.dout (fifo2_rd_data ), // output wire [15 : 0] dout
.full (fifo2_full ), // output wire full
.empty (fifo2_empty ), // output wire empty
.data_count (fifo2_data_count ) // output wire [10 : 0] data_count
);

always @(posedge sclk) begin
if (rst_n == 1’b0) begin // reset
fifo2_rd_en <= 0;
end
else if (fifo2_empty == 1’b1) begin
fifo2_rd_en <= 0;
end
else if (cnt_fifo_wr == 12’d2047) begin
fifo2_rd_en <= 1;
end
end

always @(posedge sclk) begin
if (rst_n == 1’b0) begin // reset
out_valid <= 0;
out_data <= 0;
end
else if (fifo2_rd_en == 1’b1 && in_valid == 1’b1) begin
out_valid <= 1;
out_data <= in_data + fifo1_rd_data + fifo2_rd_data;
end
else begin
out_valid <= 0;
out_data <= 0;
end
end

endmodule

附:仿真激励代码:

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/06/04 11:35:58
// Design Name:
// Module Name: tb_top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//

module tb_top (); /* this is automatically generated */

// clock
reg clk;
initial begin
	clk = 'b0;
	forever #(5) clk = ~clk;
end

// synchronous reset
reg rst_n;
initial begin
	rst_n <= 'b0;
	repeat(100)@(posedge clk);
	rst_n <= 'b1;
end

// (*NOTE*) replace reset, clock, others

reg         in_valid;
reg  [15:0] in_data;
wire        out_valid;
wire [15:0] out_data;

reg  [11:0]	cnt_in_valid = 0;
wire [ 1:0]	row;
wire [ 9:0]	col;


always @(posedge clk) begin
	if (rst_n == 1'b0) begin		// reset
		in_valid	<=	0;
		in_data		<=	0;
		cnt_in_valid<=	0;
	 end
	else if (cnt_in_valid <= 'd3071) begin
		in_valid	<=	1;
		in_data		<=	{$random}%1024;
		cnt_in_valid<=	cnt_in_valid + 1;			
	 end
	else begin
		in_valid	<=	0;
		in_data		<=	0;
		cnt_in_valid<=	cnt_in_valid;
	 end
 end

assign	row	=	cnt_in_valid[11:10];
assign	col	=	cnt_in_valid[9:0];

top inst_top (
	.sclk      (clk),
	.rst_n     (rst_n),
	.in_valid  (in_valid),
	.in_data   (in_data),
	.out_valid (out_valid),
	.out_data  (out_data)
);

endmodule

链接:https://pan.baidu.com/s/1qMD6M91oXo_Ls920Y0fLqA
提取码:02ko
复制这段内容后打开百度网盘手机App,操作更方便哦
fpga培训就业班|FPGA视频课程就业班|FPGA设计服务|FPGA企业内训|PCIE接口培训课程|码课网 V3学院
fpga培训就业班|FPGA视频课程就业班|FPGA设计服务|FPGA企业内训|PCIE接口培训课程|上海fpga就业培训班-v3学院(www.v3edu.org)
威三学院长期开FPGA人工智能就业班,FPGA软件无线电、通信IC就业班

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值