利用FPGA做FIFO测试

很久没有更新博客了,很抱歉,博主近两个月的时间做了一个决定,开始转战fpga领域,毕竟项目要落地,一味用电脑做也不行,所以以后的大方向是用FPGA来实现图像处理,怎么说呢,研究方向不变,但是过程变了。

好了废话不多说,开始来实现。fifo即先进先出,它的输入输出参数如下:

module fifo (
	clock,
	data,
	rdreq,
	wrreq,
	empty,
	full,
	q,
	usedw);

下面解释一下,clock为时钟信号,data为输入数据,rdreq为读使能信号,wrreq为写使能信号,empty为数据是否为空,full为数据是否要存满,q为输出数据,usedw为片内数据数量

需要注意的是,写使能信号为真时,在时钟上升沿时有效,data数据存入,同理,读使能也是。但是需要注意的一点就是因为每个时钟上升沿会判断读使能和写使能,所以在某个延时电路中需要及时关闭读使能或者写使能,否则下一个时钟上升沿会更新数据从而造成读写错误设计思路是:通过串口输入一组数据到fifo,然后按下按键,数据依次输出

下面来看代码

module uart_rx(
clk,
rst,
data_in,
Data,
led,
isDone
);

input clk;
input rst;
input data_in;
output [3:0]led;
output [7:0]Data;
output reg isDone;
reg [15:0]bps_count;
always@(posedge clk or negedge rst)
if(!rst)
	bps_count<=16'b0;
else if(bps_count==16'd5207)
	bps_count<=16'b0;
else if(isCount)
	bps_count<=bps_count+1'b1;
else
	bps_count<=16'd0;

reg pin_1;
reg pin_2;
wire high_pin;
always@(posedge clk or negedge rst)
if(!rst)
	begin
		pin_1<=1'b1;
		pin_2<=1'b1;
	end
else
	begin
		pin_1<=data_in;
		pin_2<=pin_1;
	end
assign high_pin=pin_2 & !pin_1;

reg isCount;
reg [7:0]rdata;
reg [3:0]i;
always@(posedge clk or negedge rst)
if(!rst)
	begin
		rdata<=8'b0;
		i<=4'd0;
		isDone<=1'b0;
		isCount <= 1'b0;
	end
else
	case(i)
		4'd0: if(high_pin) begin i<=i+1'b1;isCount <= 1'b1;end
		4'd1: if(bps_count==16'd2604)begin
				i<=i+1'b1;
				end
		4'd2: if(bps_count==16'd2604)begin
				rdata[0]<=data_in;
				i<=i+1'b1;
				end
		4'd3: if(bps_count==16'd2604)begin
				rdata[1]<=data_in;
				i<=i+1'b1;
				end
		4'd4: if(bps_count==16'd2604)begin
				rdata[2]<=data_in;
				i<=i+1'b1;
				end
		4'd5: if(bps_count==16'd2604)begin
				rdata[3]<=data_in;
				i<=i+1'b1;
				end
		4'd6: if(bps_count==16'd2604)begin
				rdata[4]<=data_in;
				i<=i+1'b1;
				end
		4'd7: if(bps_count==16'd2604)begin
				rdata[5]<=data_in;
				i<=i+1'b1;
				end
		4'd8: if(bps_count==16'd2604)begin
				rdata[6]<=data_in;
				i<=i+1'b1;
				end
		4'd9: if(bps_count==16'd2604)begin
				rdata[7]<=data_in;
				i<=i+1'b1;
				end
		4'd10: if(bps_count==16'd2604)begin
				i<=i+1'b1;
				end
		4'd11: if(bps_count==16'd2604)begin
				i<=i+1'b1;
				end
		4'd12: if(bps_count==16'd2604)begin
			   isDone<=1'b1;
				isCount <= 1'b0;
				i<=i+1'b1;
				end
		4'd13: begin
			   isDone<=1'b0;
				i<=4'd0;
				end
	endcase
	
assign Data=rdata;
assign led=rdata[3:0];
endmodule





module uart(
clk,
rst,
data,
key,
isbegin,
data_out,
isdone,
is_start,
i
);

input clk;
input rst;
input [7:0]data;
input key;
input isbegin;
output reg data_out;
output reg isdone;
output reg [3:0]i;
output reg is_start;
always@(posedge clk or negedge rst)
if(!rst)
	is_start<=1'b0;
else if(!key)
	is_start<=1'b1;

reg [7:0]rdata;
always@(posedge clk or negedge rst)
if(!rst)
	rdata<=8'b0;
else 
	rdata<=data;

reg [15:0]bps_count;
always@(posedge clk or negedge rst)
if(!rst)
	bps_count<=16'b0;
else if(bps_count==16'd5207)
	bps_count<=16'b0;
else if(isCount)
	bps_count<=bps_count+1'b1;
else
	bps_count<=16'd0;
	

reg isCount;
always@(posedge clk or negedge rst)
if(!rst)
begin
	isdone<=1'b0;
	i<=4'd0;
	isCount <= 1'b0;
end
else if(isbegin&isEn&is_start)
	case(i)
	4'd0:begin
	i<=i+1'b1;
	isCount <= 1'b1;
	end
	4'd1:begin i<=i+1'b1;end
	4'd2:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	data_out<=1'b0;
	end
	4'd3:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	data_out<=rdata[0];
	end
	4'd4:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	data_out<=rdata[1];
	end
	4'd5:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	data_out<=rdata[2];
	end
	4'd6:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	data_out<=rdata[3];
	end
	4'd7:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	data_out<=rdata[4];
	end
	4'd8:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	data_out<=rdata[5];
	end
	4'd9:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	data_out<=rdata[6];
	end
	4'd10:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	data_out<=rdata[7];
	end
	4'd11:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	data_out<=1'b1;
	end
	4'd12:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	data_out<=1'b1;
	end
	4'd13:if(bps_count==16'd2604)begin
	i<=i+1'b1;
	isCount <= 1'b0;
	isdone<=1'b1;
	end
	4'd14:begin
	i<=1'b0;
	isdone<=1'b0;
	end
	endcase

	
reg [26:0]Count_Sec; 
always @ ( posedge clk or negedge rst )
  if( !rst )
		Count_Sec <= 27'd0;
  else if( Count_Sec == 27'd49_999_999 )
		Count_Sec <= 27'd0;
  else if(is_start)
		Count_Sec <= Count_Sec + 1'b1;
  else
		Count_Sec <= 27'd0;
				
reg isEn; 
always @ ( posedge clk or negedge rst )
if( !rst )
  begin
		isEn <= 1'b0;
  end	
else if( isdone )
  begin
		isEn <= 1'b0;
  end
else if( Count_Sec == 27'd49_999_999 )
	isEn <= 1'b1;//每隔一秒发送一次数据
endmodule



module control(
clk,
rst,
isDone,
isdone,
empty,
full,
is_start,
i,
rdreq,
wrreq,
isbegin
);

input clk;
input rst;
input isDone;
input isdone;
input empty;
input full;
input is_start;
input [3:0]i;
output reg rdreq;
output reg wrreq;
output reg isbegin;

always@(posedge clk or negedge rst)
if(!rst)
	wrreq<=1'b0;
else if(isDone&&!full)
	wrreq<=1'b1;
else
	wrreq<=1'b0;
	
	
always@(posedge clk or negedge rst)
if(!rst)
	isbegin<=1'b0;
else if(!empty)
	isbegin<=1'b1;
else if(empty&isdone)
	isbegin<=1'b0;

always@(posedge clk or negedge rst)
if(!rst)
	rdreq<=1'b0;
else if(is_start&&(i==4'd13))
	rdreq<=1'b1;
else
	rdreq<=1'b0;



endmodule







// megafunction wizard: %FIFO%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: scfifo 

// ============================================================
// File Name: fifo.v
// Megafunction Name(s):
// 			scfifo
//
// Simulation Library Files(s):
// 			altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 11.0 Build 208 07/03/2011 SP 1 SJ Full Version
// ************************************************************


//Copyright (C) 1991-2011 Altera Corporation
//Your use of Altera Corporation's design tools, logic functions 
//and other software and tools, and its AMPP partner logic 
//functions, and any output files from any of the foregoing 
//(including device programming or simulation files), and any 
//associated documentation or information are expressly subject 
//to the terms and conditions of the Altera Program License 
//Subscription Agreement, Altera MegaCore Function License 
//Agreement, or other applicable license agreement, including, 
//without limitation, that your use is for the sole purpose of 
//programming logic devices manufactured by Altera and sold by 
//Altera or its authorized distributors.  Please refer to the 
//applicable agreement for further details.


// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module fifo (
	clock,
	data,
	rdreq,
	wrreq,
	empty,
	full,
	q,
	usedw);

	input	  clock;
	input	[7:0]  data;
	input	  rdreq;
	input	  wrreq;
	output	  empty;
	output	  full;
	output	[7:0]  q;
	output	[7:0]  usedw;

	wire [7:0] sub_wire0;
	wire  sub_wire1;
	wire  sub_wire2;
	wire [7:0] sub_wire3;
	wire [7:0] usedw = sub_wire0[7:0];
	wire  empty = sub_wire1;
	wire  full = sub_wire2;
	wire [7:0] q = sub_wire3[7:0];

	scfifo	scfifo_component (
				.clock (clock),
				.data (data),
				.rdreq (rdreq),
				.wrreq (wrreq),
				.usedw (sub_wire0),
				.empty (sub_wire1),
				.full (sub_wire2),
				.q (sub_wire3),
				.aclr (),
				.almost_empty (),
				.almost_full (),
				.sclr ());
	defparam
		scfifo_component.add_ram_output_register = "OFF",
		scfifo_component.intended_device_family = "Cyclone IV E",
		scfifo_component.lpm_numwords = 256,
		scfifo_component.lpm_showahead = "OFF",
		scfifo_component.lpm_type = "scfifo",
		scfifo_component.lpm_width = 8,
		scfifo_component.lpm_widthu = 8,
		scfifo_component.overflow_checking = "ON",
		scfifo_component.underflow_checking = "ON",
		scfifo_component.use_eab = "ON";


endmodule

// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
// Retrieval info: PRIVATE: Clock NUMERIC "0"
// Retrieval info: PRIVATE: Depth NUMERIC "256"
// Retrieval info: PRIVATE: Empty NUMERIC "1"
// Retrieval info: PRIVATE: Full NUMERIC "1"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"
// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
// Retrieval info: PRIVATE: Optimize NUMERIC "0"
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
// Retrieval info: PRIVATE: UsedW NUMERIC "1"
// Retrieval info: PRIVATE: Width NUMERIC "8"
// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"
// Retrieval info: PRIVATE: diff_widths NUMERIC "0"
// Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
// Retrieval info: PRIVATE: output_width NUMERIC "8"
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
// Retrieval info: PRIVATE: rsFull NUMERIC "0"
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "256"
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"
// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8"
// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "8"
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"
// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty"
// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL "full"
// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq"
// Retrieval info: USED_PORT: usedw 0 0 8 0 OUTPUT NODEFVAL "usedw[7..0]"
// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq"
// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
// Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 0
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0
// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
// Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
// Retrieval info: CONNECT: usedw 0 0 8 0 @usedw 0 0 8 0
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_bb.v TRUE
// Retrieval info: LIB_FILE: altera_mf










module fifo_test(
clk,
rst,
data_in,
key,
data_out,
led
);
input clk;
input rst;
input data_in;
input key;
output data_out;
output [3:0]led;

wire [7:0]Data;
wire isDone;
uart_rx uart_rx(
.clk(clk),
.rst(rst),
.data_in(data_in),
.Data(Data),
.led(led),
.isDone(isDone)
);

wire [7:0]data;
wire isdone;
wire is_start;
wire [3:0]i;
uart uart(
.clk(clk),
.rst(rst),
.data(data),
.key(key),
.isbegin(isbegin),
.data_out(data_out),
.isdone(isdone),
.is_start(is_start),
.i(i)
);

wire wrreq;
wire rdreq;
wire empty;
wire full;
fifo fifo(
.clock(clk),
.data(Data),
.rdreq(rdreq),
.wrreq(wrreq),
.empty(empty),
.full(full),
.q(data)
);

wire isbegin;
control control(
.clk(clk),
.rst(rst),
.isDone(isDone),
.isdone(isdone),
.isbegin(isbegin),
.empty(empty),
.full(full),
.is_start(is_start),
.rdreq(rdreq),
.wrreq(wrreq),
.i(i)
);
endmodule


需要注意的一点就是,我在quartus下上电实验发现一个奇怪的现象,就是串口每次需要先发送一次数据在让读使能为1,然后一次输入。我个人解释是,因为串口存在缓冲,需要清空,所以第一次发送实际并没有发送出来,当然如果先让读使能为真然后发送,第一个数据会乱码,因为它和缓冲区冲突了,后面的不变。这个不知道是不是bug,哎搞了好久。。。

最后总结,学FPGA的道路很漫长。。。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FPGA 同步 FIFO 是一种用于在 FPGA 设备中实现数据缓冲和数据转移的组件。它由一个读取指针和一个写入指针组成,可以实现读写操作的同步和互斥。 使用 FPGA 同步 FIFO 的一个常见场景是在不同频率的数据传输之间进行数据缓冲和同步。当输入以不同频率产生数据时,为了保证数据的可靠传输和处理,可以使用同步 FIFO 来缓冲输入数据,并在输出端以相同或不同的频率读取数据。 FPGA 同步 FIFO 的实现可以采用 FPGA 内部的存储单元,如 Block RAM 或 Distributed RAM。写入操作将数据写入 FIFO 的写入指针所指向的位置,并将写入指针前移。读取操作将数据从 FIFO 的读取指针所指向的位置读取出来,并将读取指针前移。读写指针的移动是同步的,以保证数据的正确性和完整性。 FPGA 同步 FIFO 的大小通常取决于数据传输的需求和 FPGA 设备的资源限制。可以根据数据产生和处理的速度来确定 FIFO 的大小,并且需要根据需要调整读写指针的顺序和移动策略,以满足数据的传输需求。 尽管 FPGA 同步 FIFO 在数据传输中起到了重要的作用,但同时也会增加设计的复杂性和资源消耗。在使用 FPGA 同步 FIFO 时,需要注意处理数据的同步和互斥问题,以及避免出现数据丢失、溢出等异常情况。 总之,FPGA 同步 FIFO 是一种用于实现数据缓冲和转移的组件,在不同频率的数据传输中发挥了关键作用。它可以通过读写指针的同步移动来保证数据的可靠性和完整性,并且可根据需求和硬件资源进行灵活调整。但同时也需要注意处理同步和互斥问题,以确保数据的正确传输。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值