单总线传输协议b2s (附全部verilog源码)
verilog 逻辑函数 串口发送

verilog 逻辑函数串口发送摘要:1.Verilog 逻辑函数概述2.串口发送原理3.Verilog 实现串口发送的逻辑函数4.应用实例正文:【1.Verilog 逻辑函数概述】Verilog 是一种硬件描述语言,主要用于数字电路和模拟混合信号电路的描述。
它的语法简洁,易于理解和使用。
在数字电路设计中,逻辑函数是基本的构建模块,通过组合这些模块可以实现复杂的数字电路。
【2.串口发送原理】串口(Serial Port)是一种计算机硬件接口,可以通过串行通信传输数据。
发送数据时,数据被逐个比特按顺序传送,这样可以减少线路的传输次数,提高通信效率。
在电子设备中,如单片机、FPGA 等,通常会使用串口进行数据通信。
【3.Verilog 实现串口发送的逻辑函数】要实现串口发送功能,首先需要设计一个状态机,控制数据的发送过程。
下面是一个简单的Verilog 代码示例,实现一个8 位串口发送器:```verilogmodule serial_port_sender(input wire clk, // 时钟信号input wire rst_n, // 低电平复位信号input wire start, // 开始发送信号input wire [7:0] data, // 发送数据output wire busy // 忙碌信号);// 定义状态机typedef enum logic [1:0] {IDLE, SENDING} state_t; state_t current_state, next_state;always_ff @(posedge clk or negedge rst_n) begin if (!rst_n) begincurrent_state <= IDLE;end else begincurrent_state <= next_state;endendalways_comb begincase (current_state)IDLE: beginif (start &&!busy) beginnext_state = SENDING;endendSENDING: beginif (data == 8"b0000_0001) begin // 发送结束标志next_state = IDLE;end else begin// 发送数据busy = 1;next_state = SENDING;endendendcaseendendmodule```【4.应用实例】上述代码实现了一个简单的8 位串口发送器。
基于verilog的很基础的RS232串口收发代码

基于verilog的很基础的RS232串口收发代码写代码,记笔记,防忘记,须牢记。
写串口的Verilog代码关键是要搞明白RS232串口的通信协议,它并不像单片机,直接读写SBUF就可实现串口的收发功能,收发整个字节。
而FPGA要一位一位的收发,因此必须了解RS232的数据格式。
起始位:RS232约定一位起始位“0”。
停止位:约定停止位为“1”。
可选一位或两位停止位。
奇偶校验位:可选。
通过串口发送数据时,要严格遵守RS232的数据格式,先发送起始位,然后是数据,最后是停止位(无奇偶校验的情况)。
通过串口接收数据时,若接收端无数据输入,会一直处于高电平,若开始接收数据,会首先收到来自串口的起始位“0”,然后是要接收的数据,最后为停止位(无奇偶校验的情况)。
所以对于接收模块,可如此设计,FPGA一直检测接收端是否有下降沿到来,直到检测到下降沿,才开始接收数据。
波特率设置的重要性不言而喻,毋庸赘述。
此设计为最基础的串口收发代码,控制逻辑简单,适合编写第一次编写串口代码的朋友。
此设计收发的数据格式为1位起始位,1位停止位,无奇偶校验位,8位数据位。
波特率为19200,代码中可随意更改。
具体Verilog代码如下:顶层模块`timescale 1ns / 1ps/////////////////////////////////////////////////////////////////// /////////////// Company : 杭州电子科技大学// Engineer : 晓晓川// Create Date : 2012.08.26// Design Name : serial_test// Module Name : serial_test// Project Name: serial_test// Target Device: CycloneII EP2C5T144C8// Tool versions: Quartus II 11.0// Revision : V1.0// Description : 一个极为简单的串口收发工程,适于串口收发的入门。
ST-BUS总线接口模块的Verilog HDL设计

ST-BUS总线接口模块的Verilog HDL设计关键字:总线转换卡驱动控制电路输入输出模块印刷电路板滤波电路整流电路引言随着数字技术的迅速发展,现代通信系统已成为一个庞大的综合化数字网络。
电信核心网络除了提供传统电话服务外,还为其它专用通信(比如警用集群通信等)提供中继服务。
电信系统一般从交换机引出E1信号线路以供其它专用通信系统接入。
为了满足电信网的接入规范,E1终端设备内部常采用一种被称为ST-BUS的总线来对需要接入通信网的各路用户数据进行排队,以便统一与E1信号进行转换,充分利用E1线路资源。
由于批量生产的接口芯片都是针对某些特定标准接口而设计,无法满足E1通信的特殊需要。
为满足多种特殊接口与电信线路间进行数据交换的需要,增加系统可重配置的灵活性,本文在所涉及项目中的E1接口转换板的设计中采用了可编程器件实现了多种特殊接口的混合接入。
为了简化问题,文中主要介绍ST-BUS总线接口收发模块的Verilog HDL设计。
ST-BUS基本原理ST-BUS(Serial Telecom BUS,串行通信总线)是卓联半导体公司根据电信应用的需要而定义的一种重要的通信设备内部总线通信协议,它可以将多路信息(包括音频、视频、控制信息以及其它数据等)进行复接或解复接,以便统一进行信号转换,实现本地设备与电信E1线路间的数据交换。
随着通信系统越来越复杂,电信设备常有局部部件的淘汰或者更新换代。
为了提高设备兼容性也便于系统升级,电信设备广泛采取了模块化设计方法,而ST -BUS就是将各功能模块连接起来协同工作的一种总线标准。
所以,不论模块的功能和外部接口怎样,只要具备ST-BUS总线接口,都可以方便地嵌入到特定的通信系统中。
根据卓联对ST-BUS的信号及时序规范所作的定义,ST-BUS是一种传输数字信息的高速同步串行通信总线,总线接口所需信号有帧同步信号、位时钟信号和串行数据信号。
帧同步信号主要有类型0和类型1两种:类型0的同步脉冲仅出现在帧的开头,如图1所示,总线上各部件将之作为重要参考信号并由此决定何时开始接收或发送数据流;类型1的同步脉冲需要维持一个完整的时隙周期(即8个位时钟周期),在此期间部件也要接收或发送信息数据,这种同步方式较少应用。
apb协议verilog代码

apb协议verilog代码APB协议Verilog代码详解引言APB(Advanced Peripheral Bus)是一种用于连接外设和处理器的总线协议,广泛应用于ARM架构的SoC(System on Chip)设计中。
本文将详细介绍APB协议的Verilog代码实现,旨在帮助读者理解APB协议的工作原理和实际应用。
一、APB协议概述APB协议是一种简单、低功耗的总线协议,它定义了外设和处理器之间的通信规则。
APB总线包含两根信号线,即PCLK(Peripheral Clock)和PRESETn(Peripheral Reset),以及多个控制信号和数据信号。
其中,PCLK用于同步数据传输,PRESETn用于复位外设。
二、APB协议的时序APB协议的时序是按照时钟信号PCLK来驱动的。
在每个时钟周期内,APB总线上的传输会按照一定的顺序和规则进行。
1. 主设备发起读传输当主设备需要从外设读取数据时,它会发起一个读传输。
读传输是通过发送一个带有外设地址和读命令的传输请求来实现的。
2. 主设备发起写传输当主设备需要向外设写入数据时,它会发起一个写传输。
写传输是通过发送一个带有外设地址、写命令和写数据的传输请求来实现的。
3. 外设响应传输在收到主设备的传输请求后,外设会根据请求类型进行相应的操作,并将操作结果返回给主设备。
外设的响应有两种类型,即OK(传输成功)和ERROR(传输失败)。
4. 传输完成无论是读传输还是写传输,一旦传输完成,主设备就会等待下一个时钟周期的到来,以进行下一次传输。
三、APB协议Verilog代码实现下面是一个简单的APB协议的Verilog代码实现示例,用于读写一个简单的外设寄存器。
```module APB (input wire PCLK,input wire PRESETn,input wire [7:0] ADDR,input wire [31:0] WDATA,output wire [31:0] RDATA,output wire PENABLE,output wire PREADY,output wire PWRITE,output wire PSEL,output wire PENABLE);reg [31:0] reg_data;reg [31:0] rdata;always @(posedge PCLK) beginif (!PRESETn)reg_data <= 0;else if (PSEL && PENABLE && PWRITE) reg_data <= WDATA;endalways @(negedge PCLK) beginif (!PRESETn)rdata <= 0;else if (PSEL && PENABLE && !PWRITE) rdata <= reg_data;endassign RDATA = rdata;assign PREADY = 1;assign PENABLE = PSEL;assign PWRITE = PSEL && PENABLE && PWRITE;assign PSEL = (ADDR == 8'h01);endmodule```四、代码解析以上代码实现了一个简单的APB总线模块。
Verilog HDL实现UDP协议传输

Verilog HDL实现UDP协议传输一、根据上一篇《网络传输协议结构》中介绍需要的模块有:1、发送数据中有校验和,需要首先建立一个校验和模块;2、在每个帧报格式下有不同的固定值需要发送,那么为了程序可读性,统一以头文件的形式建立这些值参数,需要建立的值参考《网络传输协议结构》;3、建立发送模块,利用case语句完成每一步定义好的数据传输;二、各个模块的接口设计1、校验和模块:clk‐‐‐‐‐‐‐‐‐‐‐‐‐125M时钟rst‐‐‐‐‐‐‐‐‐‐‐‐‐复位enable‐‐‐‐‐‐‐‐使能checkdata‐‐‐‐‐校验的数据checksum‐‐‐‐计算结果finish‐‐‐‐‐‐‐‐‐‐完成标志位2、固定参数头文件:在这里没有所谓的接口,只要在发送模块中的通过include调用语句,以计算机的IP、mac地址为例:parameter PC_ip = 32'hc0a80001 //定义参数PC_ip值为32位16进制数c0a80001parameter PC_mac = 48'h010********* //定义参数PC_mac值为48位16进制数010*********这样将每个固定的值,按照自己的方式起个名字就可以了,在发送模块中直接可以应用类似于PC_ip,PC_mac这样的名字了。
3、发送模块:clk‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐125M时钟,Rst‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐复位信号,transmit_en‐‐‐‐‐‐‐‐‐‐使能信号,readreq‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐读数据使能信号,phydata‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐发送的数据,IP_checksum‐‐‐‐‐‐‐‐‐计算好的校验和数据,txd_out‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐发送到物理接口的数据,txen_out‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐发送到物理接口的写控制信号,txc‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐发送到物理接口的时钟信号125M,transmit_finish‐‐‐‐‐‐‐‐发送完成信号,三、校验和实现计算校验和在《网络传输协议结构》这个中需要的部分已经提到方法,就是16位数据的加法运算,有进位位乖乖的加1吧,将所有数据加完取反,赋值到checksum输出引脚,等待以下应用吧。
verilog 十位二进制代码

verilog 十位二进制代码
Verilog是一种硬件描述语言,用于设计数字电路和系统。
在Verilog中,二进制代码是用来表示数字信号的最基本的方法之一。
本文将介绍一种Verilog代码,用于表示十位二进制数字。
在Verilog中,二进制代码可以使用0和1来表示。
十位二进制数字可以用十个0或1来表示,例如:
0000000000
1111111111
在Verilog中,我们可以使用wire或reg来定义变量。
wire用于表示连续信号,而reg用于表示存储信号。
对于十位二进制数字,我们可以使用reg来定义:
reg [9:0] binary_number;
上述代码定义了一个十位二进制数字,范围为9到0。
我们可以使用assign语句将二进制数字赋值给变量:
assign binary_number = 10'b010*******;
上述代码将二进制数字010*******赋值给变量binary_number。
我们也可以使用input语句来输入十位二进制数字:
input [9:0] binary_input;
上述代码定义了一个输入变量,范围为9到0。
我们可以使用$display语句来输出十位二进制数字:
$display('Binary number is: %b', binary_number);
上述代码将十位二进制数字输出为字符串。
%b表示输出为二进
制数字。
以上是Verilog十位二进制代码的简单介绍。
在实际应用中,我们可以使用更多的Verilog语句和功能来实现更复杂的电路和系统。
VerilogHDL代码_AHB总线_master部分

V e r i l o g H D L代码_A H B总线_m a s t e r部分------------------------------------------作者xxxx------------------------------------------日期xxxxmodule ahb_master(HBUSREQ,HLOCK,HTRANS,HADDR,HWRITE,HSIZE,HBURST,HWDATA,HS EL,hcount,HRESETn,HCLK,HGRANT,HREADY,HRESP,HRDATA,BUSREQ,AD DREQ,WRITE,ADDR,SIZE,BURST,SEL,TRANS,WDATA);output HBUSREQ,HLOCK,HWRITE;output [1:0]HTRANS,HSEL;output [31:0]HADDR,HWDATA;output [2:0]HSIZE,HBURST;input HGRANT,HREADY,HCLK,HRESETn,BUSREQ,ADDREQ,WRITE;input [31:0]ADDE,WDATA;input [2:0]SIZE,BURST;input [1:0]HRESP,SEL,TRANS;input [31:0]HRDATA;reg HBUSRREQ,HLOCK,HWRITE,hcount;reg [1:0]HTRANS,HSEL;reg [31:0]HADDR,HWDATA;reg [2:0]HSIZE,HBURST;wire HGRANT,HREADY,HCLK,HRESETn,WRITE;wire [31:0]ADDR,WDATA;wire [2:0]SIZE,BURST;wire [1:0]HRESP,SEL,TRANS;wire [31:0]HRDATA;reg bus_reg,adde_reg,new_hready,old_hready;reg [31:0]RDATA;reg [31:0]h_addr;parameter OKAY=2'b00ERROR=2'b01RETRY=2'b10SPLIT=2'b11;always @(posedge HCLK)beginif(!HRESETn)beginHBUSREQ=0;HLOCK=0;HWRITE=0;HTRANS=2'b00;HSEL=2'b00;HADDR=32'h000000000; HWDATA=32'h000000000; HSIZE=2'b00;HBURST=2'b00;bus_reg=0;addr_reg=0;new_hready=0;old_hready=0;hcount=0;endendalways @(posedge HCLK) beginif(HRESETn)beginif(!addr_reg)beginif(ADDREQ)beginHADDR=ADDR;h_addr=ADDR;HWRITE=WRITE;HSIZE=SIZE;HBURST=BURST;HSEL=SEL;HTRANS=TRANS;addr_reg=1'b1;HWDATA=32'h000000000; endendelse if(addr_reg)beginHADDR=32'h000000000; HWRITE=1'b0;HSIZE=3'b000;HBURST=3'b000;HTRANS=2'b00;addr_reg=1'b0;endif(!ADDREQ)beginif(WRITE)beginhcount=0;case({TRANS})2'b00:beginHWDATA=WDATA;if(HREADY && !new_hready && HRESP==ERROR) new_hready=1;else if(new_hready!=old_hready)HWDATA=32'h00000000;end2'b01:beginhcount=hcount+1;new_hready=0;HWDATA=WDATA;if(HREADY &&!new_hready && HRESP)new_hready=1;else if(new_hready!=old hready)hWDATA=32'h00000000;end2'b10:beginHWDATA=32'h00000000;end2'b11:beginhcount=hcount+1;HWDATA=WDATA;if(HREADY && HRESP==OKAY)beginif(!new_hready)new_hready=1;endelse if(new_hready!=old_hready)beginHWDATA=WDATA;new_hready=0;endelse if(HREADY && HRESP==ERROR)beginHWDATA=32'h00000000;endendendcaseendelse if(!WRITE)begincase({TRANS})2'b00:beginif(!HREADY)RDATA=HRDATA;else if(HREADY)RDATA=32'h00000000; end2'b01:beginif(!HREADY)beginRDATA=HRDATA;if(HBURST==000)h_addr=h_addr+1;elseh_addr=h_addr-1;endelse if(HREADY)RDATA=32'h00000000; end2'b10:beginRDATA=32'h00000000; end2'b11:beginif(!HREADY)beginRDATA=HRDATA;if(HBURST==000)h_addr=h_addr+1;elseh_addr=h_addr-1;endendcaseendendendendmodulemodule ram_top(HCLK ,HRESETn ,HSEL_s ,HADDR_s ,HBURST_s ,HTRANS_s ,HRDATA_s ,HWDATA_s ,HWRITE_s ,HREADY_s ,HRESP_s);input HCLK ;input HRESETn ;input HSEL_s ;input [19:0] HADDR_s ;input [2:0] HBURST_s ;input [1:0] HTRANS_s ;input [31:0] HWDATA_s ; input HWRITE_s ;output [1:0] HRESP_s ;output [31:0] HRDATA_s ; output HREADY_s ;wire [31:0] ram_RDATA ;wire [17:0] ram_ADDR ;wire [31:0] ram_WDATA ; wire ram_WRITE ;ram_ahbif U_ram_ahbif (.HCLK (HCLK ),.HRESETn (HRESETn ),.HSEL_s (HSEL_s ),.HADDR_s (HADDR_s ),.HBURST_s (HBURST_s ),.HTRANS_s (HTRANS_s ),.HRDATA_s (HRDATA_s ),.HWDATA_s (HWDATA_s ), .HWRITE_s (HWRITE_s ),.HREADY_s (HREADY_s ),.HRESP_s (HRESP_s ),.ram_RDATA (ram_RDATA ), .ram_ADDR (ram_ADDR ),.ram_WDATA (ram_WDATA ), .ram_WRITE (ram_WRITE ) );ram_infer U_ram_infer(.q (ram_RDATA ),.a (ram_ADDR ),.d (ram_WDATA ),.we (ram_WRITE ),.clk (HCLK ));endmodulemodule ram_infer(q ,a ,d ,we ,clk);output [31:0] q ;input [31:0] d ;input [17:0] a ;input we ;input clk ;reg [31:0] mem [262143:0] ; always @(posedge clk) beginif (we)beginmem[a] <= d;endendassign q = mem[a]; endmodulemodule ram_ahbif(HCLK ,HRESETn ,HSEL_s ,HADDR_s ,HBURST_s ,HTRANS_s ,HRDATA_s ,HWDATA_s ,HWRITE_s ,HREADY_s ,HRESP_s ,ram_RDATA ,ram_ADDR ,ram_WDATA ,ram_WRITE);/////////////////////////////////////////declaration of input & output///////////////////////////////////////input HCLK ;input HRESETn ;input HSEL_s ;input [19:0] HADDR_s ;input [2:0] HBURST_s ;input [1:0] HTRANS_s ;input [31:0] HWDATA_s ;input HWRITE_s ;output [1:0] HRESP_s ;output [31:0] HRDATA_s ;output HREADY_s ;input [31:0] ram_RDATA ;output [17:0] ram_ADDR ;output [31:0] ram_WDATA ;output ram_WRITE ;/////////////////////////////////////////declaration of registers & wires/////////////////////////////////////// wire [1:0] HRESP_s ;wire [31:0] HRDATA_s ;reg HREADY_s ;wire [31:0] ram_WDATA ;reg [17:0] ram_ADDR ;reg ram_WRITE ;wire wr_en ;wire rd_en ;wire ready_en ;/////////////////////////////////////////program & function///////////////////////////////////////assign HRESP_s = 2'b00;always@(posedge HCLK or negedge HRESETn)begin //HSIZE = 3'b010--32bitsif(!HRESETn) beginram_ADDR <= 18'b000000000000000000;endelse if (HSEL_s == 1'b1)beginram_ADDR <= HADDR_s[19:2];endendassign wr_en = HSEL_s & HTRANS_s[1] & HWRITE_s; always@(posedge HCLK or negedge HRESETn)beginif(!HRESETn)beginram_WRITE <= 1'b0;endelse if(wr_en)beginram_WRITE <= 1'b1;endelsebeginram_WRITE <= 1'b0;endendassign ram_WDATA= HWDATA_s;assign HRDATA_s = ram_RDATA;assign ready_en = HSEL_s & HTRANS_s[1]; always@(posedge HCLK or negedge HRESETn) beginif(!HRESETn)beginHREADY_s <= 1'b0;endelse if(ready_en)beginHREADY_s <= 1'b1;endelsebeginHREADY_s <= 1'b0;endendendmodule。
IIS总线协议【范本模板】

一、I2S总线概述音响数据的采集、处理和传输是多媒体技术的重要组成部分。
众多的数字音频系统已经进入消费市场,例如数字音频录音带、数字声音处理器。
对于设备和生产厂家来说,标准化的信息传输结构可以提高系统的适应性。
I2S(Inter—IC Sound)总线是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准,该总线专责于音频设备之间的数据传输,广泛应用于各种多媒体系统。
二、I2S总线规范I2S总线拥有三条数据信号线:1、SCK: (continuous serial clock)串行时钟对应数字音频的每一位数据,SCK都有1个脉冲。
SCK的频率=2×采样频率×采样位数。
2、WS: (word select)字段(声道)选择用于切换左右声道的数据.WS的频率=采样频率。
命令选择线表明了正在被传输的声道。
WS为“1”表示正在传输的是左声道的数据。
WS为“0”表示正在传输的是右声道的数据。
WS可以在串行时钟的上升沿或者下降沿发生改变,并且WS信号不需要一定是对称的。
在从属装置端,WS在时钟信号的上升沿发生改变。
WS总是在最高位传输前的一个时钟周期发生改变,这样可以使从属装置得到与被传输的串行数据同步的时间,并且使接收端存储当前的命令以及为下次的命令清除空间。
3、SD:(serial data) 串行数据用二进制补码表示的音频数据。
I2S格式的信号无论有多少位有效数据,数据的最高位总是被最先传输(在WS变化(也就是一帧开始)后的第2个SCK脉冲处),因此最高位拥有固定的位置,而最低位的位置则是依赖于数据的有效位数。
也就使得接收端与发送端的有效位数可以不同。
如果接收端能处理的有效位数少于发送端,可以放弃数据帧中多余的低位数据;如果接收端能处理的有效位数多于发送端,可以自行补足剩余的位(常补足为零).这种同步机制使得数字音频设备的互连更加方便,而且不会造成数据错位。
为了保证数字音频信号的正确传输,发送端和接收端应该采用相同的数据格式和长度。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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 LiuE-mail:*************************File Name: b2s_transmitter.vFunction: 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)begincase(state)//初始化0: begincount<=0;b2s_dout_r<=1;if(cnt==19) //b2s_dout_r高电平持续20个时钟beginstate<=1;cnt<=0;endelsebegincnt<=cnt+1;endend//开始信号时序1: beginb2s_dout_r<=0;if(cnt==19) //b2s_dout_r低电平持续20个时钟beginstate<=2;cnt<=0;endelsebegincnt<=cnt+1;endend2: beginb2s_dout_r<=1;if(cnt==19) //b2s_dout_r高电平持续20个时钟begincnt<=0;state<=3;endelsebegincnt<=cnt+1;endend//待发送数据的逻辑电平判断3: beginif(din[count]==1)state<=4;elsestate<=8;end//逻辑1的发送时序4: beginb2s_dout_r<=0;if(cnt==9) //b2s_dout_r低电平持续10个时钟begincnt<=0;state<=5;endelsebegincnt<=cnt+1;endend5: beginb2s_dout_r<=1;if(cnt==29) //b2s_dout_r高电平持续30个时钟begincnt<=0;state<=6;endelsebegincnt<=cnt+1;endend//逻辑0的发送时序8: beginb2s_dout_r<=0;if(cnt==29) //b2s_dout_r低电平持续30个时钟begincnt<=0;state<=9;endelsebegincnt<=cnt+1;endend9: beginb2s_dout_r<=1;if(cnt==9) //b2s_dout_r高电平持续10个时钟begincnt<=0;state<=6;endelsebegincnt<=cnt+1;endend//统计已发送数据位数6: begincount<=count+1'b1;state<=7;end7: beginif(count==WIDTH) //当一组数据所有位发送完毕,返回并继续下一次发送beginb2s_dout_r<=1;if(cnt==999) //b2s_dout_r高电平持续1000个时钟begincnt<=0;state<=0;endelsebegincnt<=cnt+1;endendelse //当一组数据未发送完毕,则继续此组下一位数据的发送state<=3;end//default值设定default: beginstate<=0;cnt<=0;count<=0;endendcaseendassign b2s_dout=b2s_dout_r;endmodule接收端源码:/*********************************************************************** *******************Author: Bob LiuE-mail:*************************File Name: b2s_receiver.vFunction: b2s接收端, 默认接收32bit数据,接收数据宽度请与发送端发送数据宽度保持一致Version: 2013-5-13 v1.0************************************************************************ ********************/module b2s_receiver(clk, //时钟基准,不限频率大小,但必须与发送端一致b2s_din, //b2s发送端发送过来的信号dout //b2s接收端解码出的数据);parameter WIDTH=32; //★设定b2s接收数据位数, 默认接收32bit数据,接收数据宽度请与发送端发送数据宽度保持一致input clk;input b2s_din;output [WIDTH-1:0] dout;//================================================== //b2s_din信号边沿检测//================================================== reg [1:0] b2s_din_edge=2'b01;always @ (posedge clk)beginb2s_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)begincase(state0)0: begintime_cnt_r<=0;state0<=1;end1: beginif(b2s_din_edge==2'b10)state0<=2;elsestate0<=state0;end2: beginif(b2s_din_edge==2'b01)beginstate0<=0;endelsetime_cnt_r<=time_cnt_r+1'b1;enddefault: begintime_cnt_r<=0;state0<=0;endendcaseendwire [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)begincase(state)0: begincount<=WIDTH;if((time_cnt>15)&&(time_cnt<25)) //判断起始信号state<=1;elsestate<=state;end1: beginif((time_cnt>5)&&(time_cnt<15)) //判断接收到的位是否为1begindout_r[WIDTH-1]<=1;state<=2;endelse if((time_cnt>25)&&(time_cnt<35)) //判断接收到的位是否为0begindout_r[WIDTH-1]<=0;state<=2;endelsebeginstate<=state;endend2: begincount<=count-1'b1; //每读取一个bit,count计数减1state<=3;end3: if(count==0) //数据读取完毕,返回并继续下一组数据的读取beginstate<=0;endelsestate<=4; //数据未读取完毕,则进行移位 4: begindout_r<=(dout_r>>1); //数据右移1位state<=1;enddefault: beginstate<=0;count<=WIDTH;endendcaseendassign dout=(count==0)?dout_r:dout; //每当一组数据读取完毕,则更新一次dout的值endmodule也许有些盆友第一次看到上面的代码,不知如何调用,所以下面给出调用示例作为参考。