很久没有更新博客了,很抱歉,博主近两个月的时间做了一个决定,开始转战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的道路很漫长。。。