赞
踩
目录
2.编写top文件,把连续接收的8bit的数据拼接成16bit数据(之后需要的位数)
团队项目需求,由于USB通信存在数据被测试环境干扰的问题,且考虑到所需通信速率不高,所以转为串口通信,下面是自己的调试记录,方便自己理解与日后回顾。
了解之前,我也很疑惑,听到大家都在说串口啦,uart啦,rs232啦,rs422啦,rs485啦,说的我一脸懵逼。后来自己了解后,才发现其实类别都不同,不能放在一起说。
串口包含了uart,还包含usb等等,可以说是uart是串口,但串口不一定是uart,我是这样理解的,不知道对不对。串口是物理层次上说的,一般有两种形式的物理接口,DB9和4针的杜邦线插口。
uart包含了rs232,rs422和rs485这些接口标准。可以说这三种接口的物理层不同,输出的电平不同,但通信协议是一样的,也就是说,编程实现是一样的,只是硬件电路电路上不同,当然其传输速率,抗干扰能力等等也自不相同。
从Xilinx嫖的uart接收与发送的例程,改改引脚定义:团队做的pcb用芯片把rs422电平转化为FPGA芯片识别的ttl电平,所以要做的就是得输进去一个rs422电平。
懵逼的我拿了个一头是usb另一头是DB9的线插上去,咦~怎么不管用啊。后来才发现这根线是usb转rs232的线。。。。。我拿了个rs232转rs422的转换器,接上后,咦~~~管用了。
后来加购了个usb直接转rs422电平的线,就可以了。(嘘,我原本以为,usb连接电脑,那边出来的只能是rs232的电平,之后回来再看的时候,不准笑话自己,哈哈哈)
代码如下(by Xilinx):
- `timescale 1ns / 1ps
- //
- //Module name uart_rx
- //Description: 16 个 clock 接收一个 bit,16 个时钟采样,取中间的采样值
- //(by_Xilinx)
- //
- module uart_rx(
- input clk, //采样时钟
- input rst_n, //复位信号
- input rx, //UART 数据输入
- output reg[7:0] dataout, //接收数据输出
- output reg rdsig,
- output reg dataerror, //数据出错指示
- output reg frameerror//帧出错指示
- );
-
-
- reg [7:0] cnt;
- reg rxbuf, rxfall, receive;
- parameter paritymode = 1'b0;
- reg presult;
- reg idle;//线路状态指示,高为线路忙,低为线路空闲
- always @(posedge clk) //检测线路的下降沿
- begin
- rxbuf <= rx;
- rxfall <= rxbuf & (~rx);
- end
- //启动串口接收程序
- always @(posedge clk)
- begin
- if (rxfall && (~idle)) begin//检测到线路的下降沿并且原先线路为空闲,启动接收数据进程
- receive <= 1'b1;
- end
- else if(cnt == 8'd168) begin //接收数据完成
- receive <= 1'b0;
- end
- end
-
- //串口接收程序, 16 个时钟接收一个 bit
-
- always @(posedge clk or negedge rst_n)
- begin
- if (!rst_n) begin
- idle<=1'b0;
- cnt<=8'd0;
- rdsig <= 1'b0;
- frameerror <= 1'b0;
- dataerror <= 1'b0;
- presult<=1'b0;
- end
- else if(receive == 1'b1) begin
- case (cnt)
- 8'd0:begin
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- rdsig <= 1'b0;
- end
- 8'd24:begin //接收第 0 位数据
- idle <= 1'b1;
- dataout[0] <= rx;
- presult <= paritymode^rx;
- cnt <= cnt + 8'd1;
- rdsig <= 1'b0;
- end
- 8'd40:begin //接收第 1 位数据
- idle <= 1'b1;
- dataout[1] <= rx;
- presult <= presult^rx;
- cnt <= cnt + 8'd1;
- rdsig <= 1'b0;
- end
- 8'd56:begin //接收第 2 位数据
- idle <= 1'b1;
- dataout[2] <= rx;
- presult <= presult^rx;
- cnt <= cnt + 8'd1;
- rdsig <= 1'b0;
- end
- 8'd72:begin //接收第 3 位数据
- idle <= 1'b1;
- dataout[3] <= rx;
- presult <= presult^rx;
- cnt <= cnt + 8'd1;
- rdsig <= 1'b0;
- end
- 8'd88:begin //接收第 4 位数据
- idle <= 1'b1;
- dataout[4] <= rx;
- presult <= presult^rx;
- cnt <= cnt + 8'd1;
- rdsig <= 1'b0;
- end
- 8'd104:begin //接收第 5 位数据
- idle <= 1'b1;
- dataout[5] <= rx;
- presult <= presult^rx;
- cnt <= cnt + 8'd1;
- rdsig <= 1'b0;
- end
- 8'd120:begin //接收第 6 位数据
- idle <= 1'b1;
- dataout[6] <= rx;
- presult <= presult^rx;
- cnt <= cnt + 8'd1;
- rdsig <= 1'b0;
- end
- 8'd136:begin //接收第 7 位数据
- idle <= 1'b1;
- dataout[7] <= rx;
- presult <= presult^rx;
- cnt <= cnt + 8'd1;
- rdsig <= 1'b1;
- end
- 8'd152:begin //接收奇偶校验位
- idle <= 1'b1;
- if(presult == rx)
- dataerror <= 1'b0;
- else
- dataerror <= 1'b1; //如果奇偶校验位不对,表示数据出错
- cnt <= cnt + 8'd1;
- rdsig <= 1'b1;
- end
- 8'd168:begin
- idle <= 1'b1;
- if(1'b1 == rx)
- frameerror <= 1'b0;
- else
- frameerror <= 1'b1; //如果没有接收到停止位,表示帧出错
- cnt <= cnt + 8'd1;
- rdsig <= 1'b1;
- end
- default: begin
- cnt <= cnt + 8'd1;
- end
- endcase
- end
- else begin
- cnt <= 8'd0;
- idle <= 1'b0;
- rdsig <= 1'b0;
- end
- end
- endmodule

- `timescale 1ns / 1ps
- //
- // Module Name: uart_tx
- // 说明:16 个 clock 发送一个 bit, 一个起始位,8 个数据位,一个校验位,一个停止位
- //
- module uart_tx(
- input clk, //UART 时钟
- input rst_n, //系统复位
- input [7:0] datain, //需要发送的数据
- input wrsig, //发送命令,上升沿有效
- output reg idle, //线路状态指示,高为线路忙,低为线路空闲
- output reg tx //发送数据信号
- );
-
-
- reg send;
- reg wrsigbuf, wrsigrise;
- reg presult;
- reg[7:0] cnt; //计数器
-
- parameter paritymode = 1'b0;
- //检测发送命令 wrsig 的上升沿
- always @(posedge clk)
- begin
- wrsigbuf <= wrsig;
- wrsigrise <= (~wrsigbuf) & wrsig;
- end
- //启动串口发送程序
- always @(posedge clk)
- begin
- if (wrsigrise && (~idle)) //当发送命令有效且线路为空闲时,启动新的数据发送进程
- begin
- send <= 1'b1;
- end
- else if(cnt == 8'd168) //一帧数据发送结束
- begin
- send <= 1'b0;
- end
- end
-
- //串口发送程序, 16 个时钟发送一个 bit
-
- always @(posedge clk or negedge rst_n)
- begin
- if (!rst_n) begin
- tx <= 1'b0;
- idle <= 1'b0;
- cnt<=8'd0;
- presult<=1'b0;
- end
- else if(send == 1'b1) begin
- case(cnt) //产生起始位
- 8'd0: begin
- tx <= 1'b0;
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- end
- 8'd16: begin
- tx <= datain[0]; //发送数据 0 位
- presult <= datain[0]^paritymode;
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- end
- 8'd32: begin
- tx <= datain[1]; //发送数据 1 位
- presult <= datain[1]^presult;
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- end
- 8'd48: begin
- tx <= datain[2]; //发送数据 2 位
- presult <= datain[2]^presult;
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- end
- 8'd64: begin
- tx <= datain[3]; //发送数据 3 位
- presult <= datain[3]^presult;
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- end
- 8'd80: begin
- tx <= datain[4]; //发送数据 4 位
- presult <= datain[4]^presult;
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- end
- 8'd96: begin
- tx <= datain[5]; //发送数据 5 位
- presult <= datain[5]^presult;
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- end
- 8'd112: begin
- tx <= datain[6]; //发送数据 6 位
- presult <= datain[6]^presult;
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- end
- 8'd128: begin
- tx <= datain[7]; //发送数据 7 位
- presult <= datain[7]^presult;
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- end
- 8'd144: begin
- tx <= presult; //发送奇偶校验位
- presult <= datain[0]^paritymode;
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- end
- 8'd160: begin
- tx <= 1'b1; //发送停止位
- idle <= 1'b1;
- cnt <= cnt + 8'd1;
- end
- 8'd168: begin
- tx <= 1'b1;
- idle <= 1'b0; //一帧数据发送结束
- cnt <= cnt + 8'd1;
- end
- default: begin
- cnt <= cnt + 8'd1;
- end
- endcase
- end
- else begin
- tx <= 1'b1;
- cnt <= 8'd0;
- idle <= 1'b0;
- end
- end
- endmodule

光这个功能,搞了我两天,我也是崩了,有时候数据不变化,有时候错位(我就是个菜鸡)。
但好在自己看着Modelsim的仿真图,一点点改好了,接收到的十六位数据也正常了。这就是乐趣所在吧,在自己操作下,一点点实现它的价值,感觉就很棒!
先用Modelsim仿真,再用signaltap抓实时数据,最后用串口助手发送所需要的数据,成功被后续芯片接收,并测的有效果,表明已通过串口发送到目标芯片,并产生所需数据。
后续和团队软件人员沟通,作出一版通过串口发送的界面,再进行调试。
第一次单独完成一个小功能,还是很开心的,记录下来,数年后再看看这个小菜鸡。
遇到问题,就想着去解决,不知道的东西,就去查资料,现在这个阶段所学的东西,肯定已经有人做过,参考一下,感谢CSDN能提供交流的平台。学无止境,继续前行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。