使用两个FIFO完成流水操作
一、设计目标
写一个FIFO控制器,控制器里有两个FIFO,输入的数据由串行接收模块(uart_rx_module)送来,一共有86行86列的数据,按0、1、2行,1、2、3行,直到最后83、84、85行,每3行为一组进行加操作,即每一组的每一列三个数进行相加,每一组要加86次。传过来的第一行数据先暂存在FIFO1中,第二行数据先暂存在FIFO2中,从第三行数据开始流水操作,即取出第一、二行的数据,与输入的新数据相加,将结果通过串行发送模块(uart_tx_module)发送出去,在相加的同时,将新数据存在FIFO2中,将FIFO2中读出的数据重新存在FIFO1中,这一组的加操作完成后,FIFO1中为第1行的数据,FIFO2中为第二行的数据,以此操作不断循环,直到最后一组。
二、设计思路
2.1 设计先知
- 串口传输过来的86×86的数据是每十个波特时间才传输一次,每一个数据传送过来的同时会有标志位拉高,只需要判断该标志位即可进行读写操作。
- 因为是三行数据相加,所以先要把前两行的数据先存到fifo1和fifo2,当第三行数据传输过来的时候,再把三个数据(两个fifo输出端和rx输出)相加。
- 第0、1、2行加完后,需要把第1、2、3行数据相加,这时第0、1、2行的数据已经全部读出来了,所以需要在相加的时候把后面两行(第1、2行)数据存到fifo里面,即相加的同时需要将fifo2的数据存入fifo1,pi_data的数据存入fifo2。
- 最后三行相加,即第83、84、85行相加,不需要写数据了,写使能可以关闭了,只需要读使能,将fifo1里面的83行读出来和将fifo2里面的84行读出来,然后与新传送过来的85行进行相加。
2.2 设计结构图
2.3 fifo核的读写时序
2.4 fifo控制模块的时序图
接口传输方向 |
接口名称 |
位宽 |
功能 |
输入 |
Pi_flag |
1 |
输入数据有效标志位,为高代表有数据输入 |
输入 |
Pi_data |
8 |
输入的一个8位数据 |
中间变量 |
Cnt_col |
8 |
列计数器,用于统计每一行写入的数据个数 |
中间变量 |
Cnt_row |
8 |
行计数器,用于统计输入数据的行数 |
中间变量 |
Wr_en_1 |
1 |
Fifo1的写使能,控制fifo数据的写入 |
中间变量 |
Wr_en_2 |
1 |
Fifo2的写使能,控制fifo数据的写入 |
中间变量 |
Data_in_1 |
8 |
Fifo1写入数据的端口 |
中间变量 |
Data_in_2 |
8 |
Fifo2写入数据的端口 |
中间变量 |
Data_out_1 |
8 |
Fifo1读出数据的端口 |
中间变量 |
Data_out_2 |
8 |
Fifo2读出数据的端口 |
中间变量 |
Rd_en |
1 |
Fifo1和Fifo2读使能,控制两个Fifo数据的读出 |
中间变量 |
Flag_add |
1 |
加操作使能信号,为高时控制三个数据相加 |
输出 |
Po_sum |
8 |
存放每一组,每列三个数据相加的结果 |
输出 |
Po_flag |
1 |
输出数据有效标志位 |
三、关键代码
3.1串口接受模块
module uart_rx_moudule(
input wire Clk,
input wire Rst_n,
input wire rx,
output reg po_flag,
output reg [7:0] po_data
); wire Rst;
assign Rst=~Rst_n; reg rx1;
reg rx2;
reg rx2_reg;
reg [12:0] cnt_baud;
parameter CNT_BAUD_MAX = 13'd5207;
parameter HALF_CNT_BAUD_MAX = 13'd2603;
reg rx_flag;
reg [3:0] bit_cnt;
reg bit_flag;
//打第一拍
always@(posedge Clk or posedge Rst)
if(Rst)
begin
rx1<=1'd0;
end
else
begin
rx1<=rx;
end
//打第二拍
always@(posedge Clk or posedge Rst)
if(Rst)
begin
rx2<=1'd0;
end
else
begin
rx2<=rx1;
end
//打第三拍
always@(posedge Clk or posedge Rst)
if(Rst)
begin
rx2_reg<=1'd0;
end
else
begin
rx2_reg<=rx2;
end
//rx_flag
always@(posedge Clk or posedge Rst)
if(Rst)
begin
rx_flag<=1'b0;
end
else if((!rx2)&&(rx2_reg))
begin
rx_flag<=1'b1;
end
else if((bit_cnt=='d8)&&(bit_flag))
begin
rx_flag<=1'b0;
end
//cnt_baud
always@(posedge Clk or posedge Rst)
if(Rst)
begin
cnt_baud<='d0;
end
else if((cnt_baud==CNT_BAUD_MAX)||(!rx_flag))
begin
cnt_baud<='d0;
end
else
begin
cnt_baud<=cnt_baud+1'b1;
end
//bit_flag
always@(posedge Clk or posedge Rst)
if(Rst)
begin
bit_flag<=1'b0;
end
else if(cnt_baud==HALF_CNT_BAUD_MAX)
begin
bit_flag<=1'b1;
end
else
begin
bit_flag<=1'b0;
end
//bit_cnt
always@(posedge Clk or posedge Rst)
if(Rst)
begin
bit_cnt<='b0;
end
else if((bit_cnt=='d8)&&(bit_flag))
begin
bit_cnt<='b0;
end
else if(bit_flag)
begin
bit_cnt<=bit_cnt+1'b1;
end
//po_data
always@(posedge Clk or posedge Rst)
if(Rst)
begin
po_data<='d0;
end
else if((bit_flag)&&(bit_cnt>='d1))
begin
po_data[bit_cnt-1'b1]<=rx2;
end
//po_flag
always@(posedge Clk or posedge Rst)
if(Rst)
begin
po_flag<=1'b0;
end
else if((bit_flag)&&(bit_cnt=='d8))
begin
po_flag<=1'b1;
end
else
begin
po_flag<=1'b0;
end
endmodule
3.2串口发送模块
module uart_tx_module(
input wire Clk,
input wire Rst_n,
input wire [7:0] pi_data,
input wire pi_flag,
output reg tx
); wire Rst;
assign Rst=~Rst_n; reg [7:0] data_temp;//数据暂存
reg tx_flag;//控制发送定时器
reg [3:0] bit_cnt;//控制发送位数
reg bit_flag;
reg [12:0] cnt_baud;
parameter CNT_BAUD_MAX = 13'd5207; //data_temp
always@(posedge Clk or posedge Rst)
if(Rst)
begin
data_temp<='d0;
end
else if(pi_flag)
begin
data_temp<=pi_data;
end
//tx_flag
always@(posedge Clk or posedge Rst)
if(Rst)
begin
tx_flag<=1'b0;
end
else if(pi_flag)
begin
tx_flag<=1'b1;
end
else if((bit_cnt=='d8)&&(bit_flag))
begin
tx_flag<=1'b0;
end //cnt_baud
always@(posedge Clk or posedge Rst)
if(Rst)
begin
cnt_baud<='d0;
end
else if((cnt_baud==CNT_BAUD_MAX)||(!tx_flag))
begin
cnt_baud<='d0;
end
else
begin
cnt_baud<=cnt_baud+1'b1;
end //bit_flag
always@(posedge Clk or posedge Rst)
if(Rst)
begin
bit_flag<=1'b0;
end
else if(cnt_baud==CNT_BAUD_MAX-1'b1)
begin
bit_flag<=1'b1;
end
else
begin
bit_flag<=1'b0;
end
//bit_cnt
always@(posedge Clk or posedge Rst)
if(Rst)
begin
bit_cnt<='d0;
end
else if((bit_cnt=='d8)&&(bit_flag))
begin
bit_cnt<='d0;
end
else if(bit_flag)
begin
bit_cnt<=bit_cnt+1'b1;
end //tx
always@(posedge Clk or posedge Rst)
if(Rst)
begin
tx<='d1;
end
else if(pi_flag)
begin
tx<=1'b0;
end
else if((bit_flag)&&(bit_cnt<='d7))
begin
tx<=data_temp[bit_cnt];
end
else if((bit_flag)&&(bit_cnt=='d8))
begin
tx<=1'b1;
end
endmodule
3.3 fifo控制模块
//=============================================================
// ---名 称:fifo_ctrl
// ---作 者:橘子哥哥
// ---Q Q :1073273114
// ---we chat:15870894502
// ---日 期:2021-1-31
// ---描 述:控制两个fifo核完成读写流水操作
//=============================================================
module fifo_ctrl(
input wire Clk,
input wire Rst_n,
input wire pi_flag,
input wire [7:0] pi_data,
output reg po_flag,
output reg [7:0] po_sum
);
wire Rst;
assign Rst=~Rst_n; reg [7:0]cnt_col;
reg [7:0]cnt_row;
reg wr_en_1;
reg wr_en_2;
reg rd_en;
wire [7:0]data_in_1;
wire [7:0]data_in_2;
wire [7:0]data_out_1;
wire [7:0]data_out_2;
reg flag_add;
//cnt_col
always@(posedge Clk or posedge Rst)
if(Rst)
begin
cnt_col<='d0;
end
else if((cnt_col=='d85)&&(pi_flag))
begin
cnt_col<='d0;
end
else if(pi_flag)
begin
cnt_col<=cnt_col+1'b1;
end
//cnt_row
always@(posedge Clk or posedge Rst)
if(Rst)
begin
cnt_row<='d0;
end
else if((cnt_col=='d85)&&(cnt_row=='d85)&&(pi_flag))
begin
cnt_row<='d0;
end
else if((cnt_col=='d85)&&(pi_flag))
begin
cnt_row<=cnt_row+1'b1;
end
//wr_en_1
always@(posedge Clk or posedge Rst)
if(Rst)
begin
wr_en_1<=1'd0;
end
else if(((pi_flag)&&(cnt_row=='d0))||((cnt_row>='d2)&&(cnt_row<='d84)&&(rd_en))||((cnt_row=='d85)&&(cnt_col=='d0)&&(rd_en)))
begin
wr_en_1<=1'b1;
end
else
begin
wr_en_1<=1'b0;
end
//wr_en_2
always@(posedge Clk or posedge Rst)
if(Rst)
begin
wr_en_2<=1'b0;
end
else if(((pi_flag)&&(cnt_row=='d1))||((cnt_row>='d2)&&(cnt_row<='d84)&&(rd_en))||((cnt_row=='d85)&&(cnt_col=='d0)&&(rd_en)))
begin
wr_en_2<=1'b1;
end
else
begin
wr_en_2<=1'b0;
end
//rd_en
always@(posedge Clk or posedge Rst)
if(Rst)
begin
rd_en<=1'b0;
end
else if((cnt_row>='d2)&&(cnt_row<='d85)&&(pi_flag))
begin
rd_en<=1'b1;
end
else
begin
rd_en<=1'b0;
end
//flag_add
always@(posedge Clk or posedge Rst)
if(Rst)
begin
flag_add<=1'b0;
end
else if(rd_en)
begin
flag_add<=1'b1;
end
else
begin
flag_add<=1'b0;
end
//po_sum
always@(posedge Clk or posedge Rst)
if(Rst)
begin
po_sum<='d0;
end
else if(flag_add)
begin
po_sum<=data_out_1+data_out_2+pi_data;
end
//po_flag
always@(posedge Clk or posedge Rst)
if(Rst)
begin
po_flag<='d0;
end
else if(flag_add)
begin
po_flag<='d1;
end
else
begin
po_flag<='d0;
end
//data_in_1
assign data_in_1=(cnt_row<='d1)?pi_data:data_out_2;
//data_in2
assign data_in_2=pi_data; fifo fifo_inst1(
.wr_clk(Clk), // input wr_clk
.rd_clk(Clk), // input rd_clk
.din(data_in_1), // input [7 : 0] din
.wr_en(wr_en_1), // input wr_en
.rd_en(rd_en), // input rd_en
.dout(data_out_1), // output [7 : 0] dout
.full(), // output full
.empty() // output empty
);
fifo fifo_inst2 (
.wr_clk(Clk), // input wr_clk
.rd_clk(Clk), // input rd_clk
.din(data_in_2), // input [7 : 0] din
.wr_en(wr_en_2), // input wr_en
.rd_en(rd_en), // input rd_en
.dout(data_out_2), // output [7 : 0] dout
.full(), // output full
.empty() // output empty
);
endmodule
3.4顶层模块
//=============================================================
// ---名 称:top_double_fifo
// ---作 者:橘子哥哥
// ---Q Q :1073273114
// ---we chat:15870894502
// ---日 期:2021-1-31
// ---描 述:双流水fifo顶层模块
//=============================================================
module top_double_fifo(
input wire Clk,
input wire Rst_n,
input wire rx,
output wire tx
);
wire flag1,flag2;
wire [7:0] data1,data2;
uart_rx_moudule uart_rx_moudule_inst(
.Clk(Clk),
.Rst_n(Rst_n),
.rx(rx),
.po_data(data1),
.po_flag(flag1)
);
fifo_ctrl fifo_ctrl_inst(
.Clk(Clk),
.Rst_n(Rst_n),
.pi_flag(flag1),
.pi_data(data1),
.po_flag(flag2),
.po_sum(data2)
);
uart_tx_module uart_tx_module_inst(
.Clk(Clk),
.Rst_n(Rst_n),
.pi_flag(flag2),
.pi_data(data2),
.tx(tx)
); endmodule
使用两个FIFO完成流水操作的更多相关文章
- 3Com Network Supervisor与IBM Tivoli NetView两款网管软件操作视频
3Com Network Supervisor与IBM Tivoli NetView两款网管软件操作视频 网管软件必须能够实实在在的给我们带来好处,对于企业网络管理来说,其作用体现在以下几个方面: ...
- IOS文件操作的两种方式:NSFileManager操作和流操作
1.常见的NSFileManager文件方法 -(NSData *)contentsAtPath:path //从一个文件读取数据 -(BOOL)createFileAtPath: path cont ...
- 2017-5-14 湘潭市赛 Partial Sum 给n个数,每次操作选择一个L,一个R,表示区间左右端点,该操作产生的贡献为[L+1,R]的和的绝对值-C。 0<=L<R<=n; 如果选过L,R这两个位置,那么以后选择的L,R都不可以再选择这两个位置。最多操作m次,求可以获得的 最大贡献和。
Partial Sum Accepted : Submit : Time Limit : MS Memory Limit : KB Partial Sum Bobo has a integer seq ...
- Leetcode 583.两个字符串的删除操作
两个字符串的删除操作 给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符. 示例 1: 输入: "se ...
- 小白两篇博客熟练操作MySQL 之 第一篇
小白两篇博客熟悉操作MySQL 之 第一篇 一.概述 1. 什么是数据库? 答: 储存数据的仓库, 如: 在ATM的事例中创建的一个db 目录, 称为数据库 2. 什么是Mysql, Oracl ...
- 小白两篇博客熟练操作MySQL 之 第二篇
小白两篇博客熟练操作MySQL 之 第二篇 一. 视图 视图是一个虚拟表,其本质是根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用名称即可获取结果集, 并可以将其当做表来使用. s ...
- 共有T个硬币,其中Z个正面,F个反面,分为两堆,要如何操作使得两堆中的正面硬币数目相等。
类似题目如下(数值是可变化的) 你的面前有30个硬币,其中有10个正面朝上,20个反面朝上,混乱在一团. 要求:现在用厚布遮住你的眼睛.要你把30个硬币分成2团,每团正面朝上的硬币个数相等.问:你要怎 ...
- Java实现 LeetCode 583 两个字符串的删除操作(求最长公共子序列问题)
583. 两个字符串的删除操作 给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符. 示例: 输入: " ...
- python两个 list 交集,并集,差集的方法+两个tuple比较操作+两个set的交集,并集,差集操作+两个dict的比较操作
转自:http://blog.chinaunix.net/uid-200142-id-3992553.html 有时候,为了需求,需要统计两个 list 之间的交集,并集,差集.查询了一些资料,现在总 ...
随机推荐
- ElasticSearch教程——filter与query对比(转学习使用)
一.数据准备 PUT /company/employee/2 { "address": { "country": "china", &quo ...
- Spring源码深度解析之数据库连接JDBC
Spring源码深度解析之数据库连接JDBC JDBC(Java Data Base Connectivity,Java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供 ...
- Openwrt_Linux_crontab任务_顺序执行脚本
Openwrt_Linux_crontab任务_顺序执行脚本 转载注明来源: 本文链接 来自osnosn的博客,写于 2020-12-21. Linux (openwrt,debian,centos. ...
- centos 8.x系统配置chrony时间同步服务
redhat/centos 7.x默认使用的时间同步服务为ntp服务,但是从redhat/centos 8开始在官方的仓库中移除了ntp软件,换成默认的chrony进行时间同步的服务,虽然也可以通过添 ...
- 一些php文件函数
当读入一个巨大的字符串的时候不能使用file_get_contents('文件名') 应该 使用fopen('文件名','r') feof('文件名') //判断是否读到了文件结尾 ******** ...
- 用隧道协议实现不同dubbo集群间的透明通信
用隧道协议实现不同dubbo集群间的透明通信 前言 笔者最近完成了一个非常有意思的隧道机制(已在产线运行),可以让注册到不同zookeeper之间的dubbo集群之间能够正常进行通信.如下图所示: 例 ...
- 基于nginx实现web服务器的双机热备
1.适用场景 对于部署重要的服务,会使用两台服务器,互相备份,共同执行同一服务.当一台服务器出现故障时,可以由另一台服务器承担服务任务,从而在不需要人工干预的情况下,自动保证系统能持续提供服务.双机热 ...
- 【C++】《C++ Primer 》第四章
第四章 表达式 一.基础 重载运算符:当运算符作用在类类型的运算对象时,用户可以自行定义其含义. 左值和右值: C中:左值可以在表达式左边,右值不能. C++中:当一个对象被用作右值的时候,用的是对象 ...
- 【EXP】exp-00091解决办法
如果遇到exp的话一般都是因为字符集的问题 解决办法: 1.在oracle中查看数据库的字符集 SQL> select userenv('language') from dual; USEREN ...
- cmd的终结工具cmder
常用快捷键 win+alt+t 打开任务设置窗口 win+alt+k 打开快捷键设置窗口 自定义屏幕分割窗口快捷键: ctl+shift+s 水平按50%比例分割 ctl+shift+v 垂直按50 ...