wordpress怎么做,排名seo怎么样,郑州seo优化公司,上海金瑞建设集团网站目录
一#xff1a;章节说明
1.1 FIFO IP简介
1.2 FIFO Generato IP 核信号框图
1.3 实验任务
二#xff1a;FIFO 写模块设计
2.1 简介
2.2 模块框图
2.3 模块端口与功能描述
2.4 写模块代码
三 FIFO 读模块设计
3.1 简介
3.2 模块框图
3.3 模块端口与功…目录
一章节说明
1.1 FIFO IP简介
1.2 FIFO Generato IP 核信号框图
1.3 实验任务
二FIFO 写模块设计
2.1 简介
2.2 模块框图
2.3 模块端口与功能描述
2.4 写模块代码
三 FIFO 读模块设计
3.1 简介
3.2 模块框图
3.3 模块端口与功能描述
3.4 读模块代码
四 顶层模块设计
4.1 概述
4.2 模块端口与功能描述
4.3 代码编写
五 仿真测试验证实现
5.1 仿真验证代码
5.2 仿真结果 一章节说明
1.1 FIFO IP简介 FIFO 本质上是由 RAM 加读写控制逻辑构成的一种先进先出的数据缓冲器其与普通存储器 RAM 的区别在于 FIFO 没有外部读写地址线使用起来非常简单但 FIFO 只能顺序写入数据并按顺序读出数据 其数据地址由内部读写指针自动加 1 完成不能像普通存储器那样可以由地址线决定读取或写入某个指定 的地址不过也正是因为这个特性使得 FIFO 在使用时并不存在像 RAM 那样的读写冲突问题。 根据 FIFO 工作的时钟域可以将 FIFO 分为同步 FIFO 和异步 FIFO 。同步 FIFO 是指读时钟和写时钟 为同一个时钟在时钟沿来临时同时发生读写操作常用于两边数据处理带宽不一致的临时缓冲。异步 FIFO 是指读写时钟不一致读写时钟是互相独立的一般用于数据信号跨时钟阈处理。 对于 FIFO 我们还需要了解一些常见参数 1、FIFO 的宽度 FIFO 一次读写操作的数据位宽 N 。 2、FIFO 的深度 FIFO 可以存储多少个宽度为 N 位的数据。 3、将空标志 almost_empty FIFO 即将被读空。 4、空标志 empty FIFO 已空时由 FIFO 的状态电路送出的一个信号以阻止 FIFO 的读操作继续从 FIFO 中读出数据而造成无效数据的读出。 5、将满标志 almost_full FIFO 即将被写满。 6、满标志 full FIFO 已满时由 FIFO 的状态电路送出的一个信号以阻止 FIFO 的写操作继续向 FIFO 中写数据而造成溢出。 7 、写时钟写 FIFO 时所遵循的时钟在每个时钟的上升沿触发。 8 、读时钟读 FIFO 时所遵循的时钟在每个时钟的上升沿触发。 这里还有两点需要大家注意 1、“ almost_empty ”和“ almost_full ”这两个信号分别被看作“ empty ”和“ full ”的警告信号他们相对于真正的空 empty 和满 full 都会 提前一个时钟周期拉高 。 2 、 FIFO 中先写入的数据被置于高位后写入的数据被置于低位由于其先入先出的特性所以读出的数据也是高位在前低位在后。这一点在读写数据位宽不对等时尤为重要例如我们写数据位宽为 8 读数据位宽为 2 当写入的数据为 11000111 时读出的数据依次为 11、00、01、11 1.2 FIFO Generato IP 核信号框图 首先说明下上图中黑色箭头表示此信号为必要信号蓝色箭头表示此信号为可选信号灰色箭头表示此信号为可选的边带信号。从图中我们可以了解到当被配置为同步 FIFO 时只使用 wr_clk 所有的输入输出信号都同步于 wr_clk 信号。而当被配置为异步 FIFO 时写端口和读端口分别有独立的时钟所有与写相关的信号都是同步于写 时钟 wr_clk 所有与读相关的信号都是同步于读时钟 rd_clk 。 这里我们对框图中的常用信号端口做一下讲解其他很少用到的信号如果大家感兴趣的话也可以在课后打开 IP 核的数据手册进行学习各常用端口的功能描述如下 1.3 实验任务 本节的实验任务是使用 Vivado 生成一个异步 FIFO 并实现以下功能当 FIFO 为空时向 FIFO 中写入数据直至将 FIFO 写满后停止写操作当 FIFO 为满时从 FIFO 中读出数据直到 FIFO 被读空后停 止读操作以此向大家详细介绍一下 FIFO IP 核的使用方法。 1.4 配置FIFO步骤 详细步骤可以参考正点原子《 领航者ZYNQ 之 FPGA 开发指南 》 P584 。 网盘链接如下 https://pan.baidu.com/s/1vXxmhg_mZm_OVg4xQeiCVQ 提取码zdyz
二FIFO 写模块设计
2.1 简介 首先介绍下 FIFO 写模块的设计在 FIFO 写模块中我们的输入信号主要有系统时钟信号写时钟域的时钟、系统复位信号因为 FIFO 的写操作需要在 FIFO 完成复位后进行所以我们还需要输入 wr_rst_busy 写复位忙信号来判断 FIFO 是否结束了复位状态实验任务中我们提到了 FIFO 为空时进行写操作因 此还需要引入一个空相关的信号这里我们引入的是 empty 空信号实验任务中我们还提到了写满了要 停止写操作所以这里我们引入了 almost_full 将满信号因为将满信号表示 FIFO 还能再进行最后一次 写操作使用这个信号的话我们正好可以在写入最后一次数据后关闭写使能当然引入 full满信号也是可以区别只是在于这么做会在写使能关断前执行一次无效的写操作。 2.2 模块框图 2.3 模块端口与功能描述 2.4 写模块代码
module fifo_wr(
//mudule clockinput wr_clk , // 时钟信号input rst_n , // 复位信号
//FIFO接口 input wr_rst_busy , // 写复位忙信号input empty , // FIFO 空信号input almost_full , // FIFO 将满信号output reg fifo_wr_en , // FIFO 写使能output reg [7:0] fifo_wr_data // 写入 FIFO 的数据); reg empty_d0;
reg empty_d1;
//因为 empty信号是和读信号的时钟同步的对于写始终来说他是异步信号所以要进行打拍处理
always(posedge wr_clk or negedge rst_n) if(!rst_n)beginempty_d0 0; empty_d1 0;endelse beginempty_d0 empty;empty_d1 empty_d0;end
//fifo写使能信号赋值当 FIFO 为空时开始写入写满后停止写
always(posedge wr_clk or negedge rst_n) if(!rst_n) fifo_wr_en 0;else if(!wr_rst_busy)beginif(empty_d1)fifo_wr_en 1; else if(almost_full)fifo_wr_en 0; else fifo_wr_en fifo_wr_en; endelsefifo_wr_en 0;//对 fifo_wr_data 赋值,0~254
always(posedge wr_clk or negedge rst_n) if(!rst_n) fifo_wr_data 0;else if(fifo_wr_en fifo_wr_data 254)fifo_wr_data fifo_wr_data 1;elsefifo_wr_data 0;endmodule三 FIFO 读模块设计
3.1 简介 首先介绍下 FIFO 读模块的设计在 FIFO 读模块中我们的输入信号主要有系统时钟信号读时钟域时钟和系统复位信号因为 FIFO 的读操作需要在 FIFO 完成复位后进行所以我们还需要输入 rd_rst_busy读复位忙信号来判断 FIFO 是否结束了复位状态实验任务中我们提到了 FIFO 为满时进行读操作因 此还需要引入一个满相关的信号这里我们引入的是 full 满信号实验任务中我们还提到了读空了要停 止读操作所以这里我们引入了 almost_empty 将空信号因为将空信号表示 FIFO 还能再进行最后一次读操作使用这个信号的话我们正好可以在读出最后一个数据后关闭读使能当然引入 empty 空信号也 是可以区别只是在于这么做会在读使能关断前执行一次无效的读操作。 3.2 模块框图 3.3 模块端口与功能描述 3.4 读模块代码
module fifo_rd(
//system clockinput rd_clk , //时钟信号input rst_n , //复位信号
//FIFO接口input rd_rst_busy , //读复位忙信号input [7:0] fifo_rd_data, //从 FIFO 读出的数据input full , //FIFO 满信号input almost_empty, //FIFO 将空信号output reg fifo_rd_en //FIFO 读使能);reg full_d0;reg full_d1;//因为 full 信号是属于 FIFO 写时钟域的所以对 full 打两拍同步到读时钟域下
always(posedge rd_clk or negedge rst_n) if(!rst_n)beginfull_d0 0; full_d1 0;endelse beginfull_d0 full;full_d1 full_d0;end //对 fifo_rd_en 进行赋值,FIFO 写满之后开始读读空之后停止读
always(posedge rd_clk or negedge rst_n) if(!rst_n) fifo_rd_en 0;else if(!rd_rst_busy)beginif(full_d1)fifo_rd_en 1; else if(almost_empty)fifo_rd_en 0; endelsefifo_rd_en 0; endmodule四 顶层模块设计
4.1 概述 本次实验的目的是为了将 Xilinx FIFO Generato IP 核配置成一个异步 FIFO 并对其进行读写操作因此可以给模块命名为 ip_fifo 因为我们做的是异步 FIFO 所以我们需要一个 PLL IP 核来输出 50MHz 的写时 钟和 100MHz 的读时钟当然输出其它频率的时钟也是可以的然后我们还需要一个写模块 fifo_wr 和 一个读模块 fifo_rd 写模块通过 FIFO 的状态来判断是否给出写请求信号和写数据读模块通过 FIFO 的状态来判断是否给出读请求信号并接收从 FIFO 中读出的数据系统时钟和系统复位是一个完整的工 程中必不可少的输入端口信号这里就不再多讲了。经过上述分析我们可以画出一个大致的模块框图如 下图所示 4.2 模块端口与功能描述 4.3 代码编写
module ip_fifo(input sys_clk,input sys_rst_n
);wire locked;
wire clk_50M;
wire clk_100M;
wire rst_n;
wire wr_rst_busy;
wire empty;
wire almost_full;
wire [7 : 0]fifo_wr_data;
wire rd_rst_busy;
wire [7 : 0]fifo_rd_data;
wire fifo_rd_en;
wire fifo_wr_en;
wire almost_empty;
wire [7 : 0]rd_data_count;
wire [7 : 0]wr_data_count;
wire full;//通过系统复位信号和时钟锁定信号来产生一个新的复位信号,代表当输出频率时钟稳定后且复位完成后才能执行
assign rst_n sys_rst_n locked;
//例化 PLL IP 核
clk_wiz_0 clk_wiz_0
(.clk_out1(clk_50M), // output clk_out1.clk_out2(clk_100M), // output clk_out2.locked(locked), // output locked.clk_in1(sys_clk) // input clk_in1
);
//例化 FIFO IP 核
fifo_generator_0 your_instance_name (.rst(~rst_n), // input wire rst.wr_clk(clk_50M), // input wire wr_clk.rd_clk(clk_100M), // input wire rd_clk.din(fifo_wr_data), // input wire [7 : 0] din.wr_en(fifo_wr_en), // input wire wr_en.rd_en(fifo_rd_en), // input wire rd_en.dout(fifo_rd_data), // output wire [7 : 0] dout.full(full), // output wire full.almost_full(almost_full), // output wire almost_full.empty(empty), // output wire empty.almost_empty(almost_empty), // output wire almost_empty.rd_data_count(rd_data_count), // output wire [7 : 0] rd_data_count.wr_data_count(wr_data_count), // output wire [7 : 0] wr_data_count.wr_rst_busy(wr_rst_busy), // output wire wr_rst_busy.rd_rst_busy(rd_rst_busy) // output wire rd_rst_busy
); //例化写 FIFO 模块
fifo_wr fifo_wr(.wr_clk(clk_50M) , // 时钟信号.rst_n(rst_n) , // 复位信号.wr_rst_busy(wr_rst_busy) , // 写复位忙信号.empty(empty) , // FIFO 空信号.almost_full(almost_full) , // FIFO 将满信号.fifo_wr_en(fifo_wr_en) ,.fifo_wr_data(fifo_wr_data) // 写入 FIFO 的数据
); //例化读 FIFO 模块
fifo_rd fifo_rd(.rd_clk (clk_100M) , //时钟信号.rst_n (rst_n) , //复位信号.rd_rst_busy (rd_rst_busy) , //读复位忙信号.fifo_rd_data (fifo_rd_data) , //从 FIFO 读出的数据.full (full) , //FIFO 满信号.almost_empty (almost_empty) , //FIFO 将空信号.fifo_rd_en (fifo_rd_en) //FIFO 读使能
); endmodule可以看出 ip_fifo 顶层模块只是例化了 FIFO IP 核 fifo_generator_0 、 PLL IP clk_wiz_0 、读模块 fifo_rd 和写模块 fifo_wr 其中写模块负责产生 FIFO IP 核写操作所需的所有数据、写请求等信 号读模块负责产生 FIFO IP 核读操作所需读请求信号并将读出的数据也连接至读模块。 因为读写模块的时钟皆来自 PLL IP 核而 PLL IP 核需要一定的时间才能输出稳定的时钟所以在第29 行代码中我们通过系统复位和时钟锁定来产生一个信号复位信号使读 / 写模块及 FIFO IP 核在时钟稳定 后才进入工作状态。 五 仿真测试验证实现
5.1 仿真验证代码
timescale 1ns / 1ps
module ip_fifo_tb();parameter CLK_PERIOD 20; //时钟周期 20ns
//reg define
reg sys_clk;
reg sys_rst_n;//信号初始化initial beginsys_clk 1b0;sys_rst_n 1b0;#200;sys_rst_n 1b1;//模拟按下复位#10000 ;sys_rst_n 0;#160 ;sys_rst_n 1;end//产生时钟always #(CLK_PERIOD/2) sys_clk ~sys_clk;ip_fifo u_ip_fifo (.sys_clk (sys_clk ),.sys_rst_n (sys_rst_n)
);endmodule5.2 仿真结果 从仿真中可见FIFO读取设计正确。 因为RAM以及FIFO在FPGA中较为重要所以后面还会有学习RAM以及FIFO的相关案例敬请期待。