1. 讲废话
小弟最近做了一个项目(用Lattice的CPLD),话说前面还算顺利,就在即将完工的时候,发现(TMD)I/O不够用,有一功能需要CPLD传输8bit数据到另一个控制器做进一步处理,but现在仅剩下一个I/O,好吧,我被卡死在这里了。终于,在一个月黑风高的夜晚(本人喜欢把气氛营造的悲壮一点,嘎嘎。。),突然想到DS18B20的单总线传输协议,以前也了解过其他的协议,心想,为嘛自己不整一个类似的东东出来yy 一下呢,所以有了此贴。
解释一下,本次原创单总线传输协议命名为b2s(不才,取了个类似I2C的名,由于本人有一个贱贱的英文名Bob,所以用了b,各位轻喷啊;s代表single,意为单线传输),本协议含传送端(transmitter)和接收端(receiver)两部分,基于verilog语言,仅使用单个I/O口进行多位数据的传输,传输方向为单向,用于I/O不够用的情况,亲测绝对可用,如果大家以后有用得到的时候,可以直接拿来使用。
本人拥抱开源,所有源码能贴出来尽量贴出来,为大家节省积分,攒RP。
废话完毕,下面为各位客官准备干货。
2. 晒干货
ps. 带★号处可根据需要进行修改.
发送端源码:
/*********************************************************************** *******************
Author: Bob Liu
E-mail:*************************
File Name: b2s_transmitter.v
Function: b2s发送端, 默认发送32bit数据,数据宽度可更改
Version: 2013-5-13 v1.0
************************************************************************ ********************/
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