一、b2s协议背景介绍

本单总线传输协议为精橙FPGA团队原创,含传送端(transmitter)和接收端(receiver)两部分,基于verilog语言,仅使用单个I/O口进行多位数据的传输,传输方向为单向,用于I/O不够用的情况,已上板验证通过,大家可直接使用。

二、b2s协议Verilog源码

ps. 带★号处可根据需要进行修改.

发送端源码:

/******************************************************************************************
File Name: b2s_transmitter.v
Function: b2s发送端,默认发送32bit数据
********************************************************************************************/ module b2s_transmitter
(
clk, //时钟基准,不限频率大小,但必须与接收端一致
din, //待发送数据
b2s_dout //b2s数据输出端口
);
parameter WIDTH=32; //★设定b2s发送数据位数 input clk;
input [WIDTH-1:0] din;
output b2s_dout; //==============================================================
//b2s数据发送时序
//==============================================================
reg b2s_dout_r;
reg [3:0] state;
reg [9:0] cnt;
reg [4:0] count; //★与发送数据位数保持一致(如发送32bit数据时,count宽度为5;发送8bit时,count宽度为4)
always @ (posedge clk)
begin
case(state)
//初始化
0: begin
count<=0;
b2s_dout_r<=1;
if(cnt==19) //b2s_dout_r高电平持续20个时钟
begin
state<=1;
cnt<=0;
end
else
begin
cnt<=cnt+1;
end
end //开始信号时序
1: begin
b2s_dout_r<=0;
if(cnt==19) //b2s_dout_r低电平持续20个时钟
begin
state<=2;
cnt<=0;
end
else
begin
cnt<=cnt+1;
end
end
2: begin
b2s_dout_r<=1;
if(cnt==19) //b2s_dout_r高电平持续20个时钟
begin
cnt<=0;
state<=3;
end
else
begin
cnt<=cnt+1;
end
end //待发送数据的逻辑电平判断
3: begin
if(din[count]==1)
state<=4;
else
state<=8;
end //逻辑1的发送时序
4: begin
b2s_dout_r<=0;
if(cnt==9) //b2s_dout_r低电平持续10个时钟
begin
cnt<=0;
state<=5;
end
else
begin
cnt<=cnt+1;
end
end
5: begin
b2s_dout_r<=1;
if(cnt==29) //b2s_dout_r高电平持续30个时钟
begin
cnt<=0;
state<=6;
end
else
begin
cnt<=cnt+1;
end
end //逻辑0的发送时序
8: begin
b2s_dout_r<=0;
if(cnt==29) //b2s_dout_r低电平持续30个时钟
begin
cnt<=0;
state<=9;
end
else
begin
cnt<=cnt+1;
end
end
9: begin
b2s_dout_r<=1;
if(cnt==9) //b2s_dout_r高电平持续10个时钟
begin
cnt<=0;
state<=6;
end
else
begin
cnt<=cnt+1;
end
end //统计已发送数据位数
6: begin
count<=count+1'b1;
state<=7;
end
7: begin
if(count==WIDTH) //当一组数据所有位发送完毕,返回并继续下一次发送
begin
b2s_dout_r<=1;
if(cnt==999) //b2s_dout_r高电平持续1000个时钟
begin
cnt<=0;
state<=0;
end
else
begin
cnt<=cnt+1;
end
end
else //当一组数据未发送完毕,则继续此组下一位数据的发送
state<=3;
end //default值设定
default: begin
state<=0;
cnt<=0;
count<=0;
end
endcase
end assign b2s_dout=b2s_dout_r; endmodule

接收端源码:

/******************************************************************************************
File Name: b2s_receiver.v
Function: b2s接收端,默认接收32bit数据
********************************************************************************************/ module b2s_receiver
(
clk, //时钟基准,不限频率大小,但必须与发送端一致
b2s_din, //b2s发送端发送过来的信号
dout //b2s接收端解码出的数据
);
parameter WIDTH=32; //★设定b2s接收数据位数 input clk;
input b2s_din;
output [WIDTH-1:0] dout; //==================================================
//b2s_din信号边沿检测
//==================================================
reg [1:0] b2s_din_edge=2'b01;
always @ (posedge clk)
begin
b2s_din_edge[0] <= b2s_din;
b2s_din_edge[1] <= b2s_din_edge[0];
end //==================================================
//time_cnt - 存储b2c_din信号下降沿及其最近的下一个上升沿之间的时间
//==================================================
reg [1:0] state0;
reg [5:0] time_cnt_r;
always @ (posedge clk)
begin
case(state0)
0: begin
time_cnt_r<=0;
state0<=1;
end
1: begin
if(b2s_din_edge==2'b10)
state0<=2;
else
state0<=state0;
end
2: begin
if(b2s_din_edge==2'b01)
begin
state0<=0;
end
else
time_cnt_r<=time_cnt_r+1'b1;
end
default: begin
time_cnt_r<=0;
state0<=0;
end
endcase
end wire [5:0] time_cnt;
assign time_cnt=(b2s_din_edge==2'b01)?time_cnt_r:'b0; //当b2s_din上升沿瞬间,读取time_cnt_r的值 //==================================================
//b2s解码时序
//==================================================
reg [2:0] state;
reg [4:0] count; //★与接收数据位数保持一致(如接收32bit数据时,count宽度为5;接收8bit时,count宽度为4)
reg [WIDTH-1:0] dout_r;
always @ (posedge clk)
begin
case(state)
0: begin
count<=WIDTH;
if((time_cnt>15)&&(time_cnt<25)) //判断起始信号
state<=1;
else
state<=state;
end
1: begin
if((time_cnt>5)&&(time_cnt<15)) //逻辑1的条件
begin
dout_r[WIDTH-1]<=1;
state<=2;
end
else if((time_cnt>25)&&(time_cnt<35))//逻辑0的条件
begin
dout_r[WIDTH-1]<=0;
state<=2;
end
else
begin
state<=state;
end
end
2: begin
count<=count-1'b1; //每读取一个bit,count减1
state<=3;
end
3: if(count==0) //数据读取完毕,返回并继续下一组数据的读取
begin
state<=0;
end
else
state<=4; //数据未读取完毕,则进行移位
4: begin
dout_r<=(dout_r>>1);//数据右移1位
state<=1;
end
default: begin
state<=0;
count<=WIDTH;
end
endcase
end assign dout=(count==0)?dout_r:dout; //每当一组数据读取完毕,则更新一次dout的值 endmodule

三、源码例化方法

调用发送端,通过单个I/O发送出一组32bit数据:

/******************************************************************************************
File Name: b2s_transmitter_test.v
Function: b2s功能测试:通过b2s transmitter模块将预置的32bit数据发送出去
********************************************************************************************/
module b2s_transmitter_test
(
input clk, //基准时钟
output b2s_dout //b2s数据输出端口
);
parameter WIDTH=32; //★设定b2s发送和接收数据位宽,此处可根据需要进行修改 //==============================================================
//预置待发送数据
//==============================================================
wire [WIDTH-1:0] din;
assign din='b01010101_00111100_11011100_11001111; //★此处可根据需要进行修改,不限于固定数值 //================================
//调用b2s_transmitter模块
//================================
b2s_transmitter
#
(
.WIDTH(WIDTH) //例化发送数据位宽
)
b2s_transmitter_isnt0
(
.clk (clk), //时钟基准,不限频率大小,但必须与接收端一致
.din (din), //待发送数据
.b2s_dout (b2s_dout) //b2s数据输出端口
); endmodule

调用接收端,解码发送端所发出的32bit数据:

/******************************************************************************************
File Name: b2s_receiver_test.v
Function: b2s功能测试:通过b2s receiver模块进行对b2s transmitter发送的数据进行接收解码
********************************************************************************************/
module b2s_receiver_test
(
input clk, //基准时钟
input b2s_dout, //b2s发送端发送过来的信号
output [31:0] dout //解码出的32bit数据
);
parameter WIDTH=32; //★设定b2s发送和接收数据位数,此处可根据需要进行修改 //================================
//调用b2s_receiver模块
//================================
b2s_receiver
#
(
.WIDTH (WIDTH) //例化接收数据位宽
)
b2s_receiver_inst0
(
.clk (clk), //时钟基准,不限频率大小,但必须与发送端一致
.b2s_din (b2s_dout), //b2s发送端发送过来的信号
.dout (dout) //b2s接收端解码出的数据
); endmodule

四、总结

本协议优缺点如下:
优点:

1. 仅使用单个I/O口进行多bit数据发送和接收(串行),可节省大量I/O口留作它用。
2. 传输频率不限,只需保证发送端和接收端工作频率一致即可。
3. 接收端所得到的信息始终是最新的,传输频率高时,近乎实时。
4. 发送和接收数据bit数量可根据需要进行增加/减少。
缺点:

1. 由于单线,无其他控制信号,发送端和接收端会一直处于工作状态(发送端一直发,接收端一直接)。

如您有此功能的定制开发或其他的FPGA设计需求,请查看下面这篇文章了解我们的业务范围和联系方式,我们将竭诚为您服务。

精橙FPGA,一个承接FPGA代码设计的资深工程师团队。

原创单总线传输协议b2s (附全部verilog源码)的更多相关文章

  1. Visual Studio 2015开发Qt项目实战经验分享(附项目示例源码)

    Visual Studio 2015开发Qt项目实战经验分享(附项目示例源码)    转 https://blog.csdn.net/lhl1124281072/article/details/800 ...

  2. HTML与CSS入门经典(第9版)试读 附随书源码 pdf扫描版​

    HTML与CSS入门经典(第9版)是经典畅销图书<HTML与CSS入门经典>的最新版本,与过去的版本相同,本书采用直观.循序渐进的方法,为读者讲解使用HTML5与CSS3设计.创建并维护世 ...

  3. NLP大赛冠军总结:300万知乎多标签文本分类任务(附深度学习源码)

    NLP大赛冠军总结:300万知乎多标签文本分类任务(附深度学习源码)       七月,酷暑难耐,认识的几位同学参加知乎看山杯,均取得不错的排名.当时天池AI医疗大赛初赛结束,官方正在为复赛进行平台调 ...

  4. Linux 部署ASP.NET SQLite 应用 的坎坷之旅 附demo及源码

    Linux 部署ASP.NET SQLite 应用 的坎坷之旅.文章底部 附示例代码. 有一台闲置的Linux VPS,尝试着部署一下.NET 程序,结果就踏上了坑之路,不过最后算是完美解决问题,遂记 ...

  5. web框架前言与学生数据库系统(附1.0源码)

    对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. import socket def f1(request): ""&quo ...

  6. 浅析 <路印协议--Loopring> 及整体分析 Relay 源码

    作者:林冠宏 / 指尖下的幽灵 前序: 路印协议功能非常之多及强大,本文只做入门级别的分析. 理论部分请细看其白皮书,https://github.com/Loopring/whitepaper 实际 ...

  7. android优化中国风应用、完整NBA客户端、动态积分效果、文件传输、小说阅读器等源码

    Android精选源码 android拖拽下拉关闭效果源码 一款优雅的中国风Android App源码 EasySignSeekBar一个漂亮而强大的自定义view15 android仿蘑菇街,蜜芽宝 ...

  8. JavaWeb宿舍管理系统(附 演示、源码下载地址)

    宿舍管理是高校管理的重要组成部分,一套优秀的管理系统不仅可以降低宿舍管理的难度,也能在一定程度上减少学校管理费用的支出,能是建设现代化高校管理体系的重要标志. 本篇文章将带你从运行环境搭建.系统设计. ...

  9. 【lwip】08-ARP协议一图笔记及源码实现

    目录 前言 8.1 IP地址与MAC地址 8.2 ARP协议简介 8.3 ARP协议报文 8.4 ARP缓存表 8.4.1 ARP缓存表简介 8.4.2 LWIP中的缓存表 8.4.3 ARP缓存表数 ...

  10. Android Gallery实现3D相册(附效果图+Demo源码)

    今天因为要做一个设置开机画面的功能,主要是让用户可以设置自己的开机画面,应用层需要做让用户选择开机画面图片的功能.所以需要做一个简单的图片浏览选择程序.最后选用Gallery作为基本控件.加入了一些炫 ...

随机推荐

  1. Yarn 3.0 Plug'n'Play (PnP) 安装和迁移

    前言 以前用 npm, 后来 yarn 火了就用 yarn. 后来 yarn 2.0 大改版, Angular 不支持就一直没用. 一直到去年的 Angular 13 才开始支持. 最近又开始写 An ...

  2. web架构-nginx负载均衡

    nginx的负载均衡 Nginx 是一个广泛使用的反向代理服务器,能够高效地实现负载均衡.负载均衡的核心作用是将来自客户端的请求分发到多个后端服务器上,从而平衡每台服务器的压力.通过Nginx,我们可 ...

  3. 揭秘!尤雨溪成立的VoidZero如何改变前端世界

    前言 Vue和Vite之父尤雨溪宣布成立公司 VoidZero,目前已经融资3200万.这篇文章欧阳将带你了解VoidZero是如何改变javascript的世界! 关注公众号:[前端欧阳],给自己一 ...

  4. Linux 循环设备 loop疑惑

    什么是loop设备? loop设备是一种伪设备,是使用文件来模拟块设备的一种技术,文件模拟成块设备后, 就像一个磁盘或光盘一样使用.在使用之前,一个 loop 设备必须要和一个文件进行连接.这种结合方 ...

  5. Windows10 安装使用 Docker

    Windows10 安装使用 Docker 下载安装 Docker Desktop https://docs.docker.com/docker-for-windows/install/ 点击运行 D ...

  6. google 搜索技巧

    size qq.com inurl : size 指定网站 inurl 这个网站的指定内容 filetype 指定搜索的文件类型

  7. websocket打造在线聊天室

    1. 常见的网络通信协议  tcp udp http 和 websocket 等 : http 超文本传输协议 ,是一个无状态,无连接,单向的应用层协议,缺点是服务器不能主动的给客户端发送消息 :消息 ...

  8. 关于自动部署 - 基于gitlab关联 腾讯云 web 应用

    gitlab 相当于 gitee 的企业版形式 : 步骤 1. 使用 Vscode 编写代码,使用 gitlab托管代码, 2. 新建腾讯云 web 应用 ,gitlab 关联 web应用, 3. 每 ...

  9. 45. beforeCreate和created的区别

    data数据和methods的方法是否存在,是否定义了 : beforeCreate 都是 undefiend :

  10. JOI 2018 Final

    A - ストーブ (Stove) 有 \(n\) 个客人将要来访,第 \(i\) 个客人的来访时间为 \([a_i, a_i + 1]\),保证 \(\forall i \in [1, n), a_i ...