重温FPGA开发12
开发 12 FPGA 重温
2023-09-14 09:09:12 时间
verilog 设计串口通信(需要手动调试)
复习我们要设计的模块,多了一个波特率输入
uart_byte_tx.v
module uart_byte_tx(
clk,
reset_n,
data,
send_en, // 什么时候开始发送
uart_tx, // 输出的串行信号
tx_done,
baud_set
) // 发完了 直呼一声,好发送下一个
input clk;
input reset_n;
input [7:0]data;
input send_en;
input [2:0]baud_set;
output reg uart_tx;
output reg tx_done;
// 译码器
// bps_dr = 0, 波特率9600
// bps_dr = 1, 波特率19200
// bps_dr = 2, 波特率38400
// bps_dr = 3, 波特率57600
// bps_dr = 4, 波特率115200
// 1000000000/9600/20 就是bps_dr的值
reg [17:0] bps_dr;
always@(*)
case(bps_dr)
0: bps_dr = 1000000000/9600/20;
1: bps_dr = 1000000000/19200/20;
2: bps_dr = 1000000000/38400/20;
3: bps_dr = 1000000000/57600/20;
4: bps_dr = 1000000000/115200/20;
default:bps_dr = 1000000000/9600/20;
endcase
// 计数器 这个需要算位宽
reg [17:0]div_cnt;
always@(posedge clk or negedge reset)
if(!reset)
div_cnt <= 0;
else if(send_en)
if(div_cnt == bps_dr - 1)
div_cnt <= 0;
else
div_cnt <= div_cnt + 1'b1;
else
div_cnt <= 0;
// 发送数据的时候 0 是起始位,1 是停止位。需要发送10段数据需要11个点来确定。需要一个计数器来计数11次
reg [3:0]bps_cnt;
always@(posedge clk or negedge reset)
if(!reset)
bps_cnt <= 0;
else if(div_cnt == bps_dr - 1) begin
if(bps_cnt == 11)
bps_cnt <= 0;
else
bps_cnt <= bps_cnt + 1'b1;
end
// 发送数据
always@(posedge clk or negedge reset)
if(!reset)
uart_tx <= 1'b1;
tx_done <= 0;
else begin
case(bps_cnt)
0: begin uart_tx <= 0; tx_done <= 1'b0; end
1: uart_tx <= Data[0];
2: uart_tx <= Data[1];
3: uart_tx <= Data[2];
4: uart_tx <= Data[3];
5: uart_tx <= Data[4];
6: uart_tx <= Data[5];
7: uart_tx <= Data[6];
8: uart_tx <= Data[7];
9: uart_tx <= Data[8];
10: uart_tx <= 1;
11: begin uart_tx <= 1; tx_done <= 1'b1; end
default: uart_tx <= 1;
endcase
end
endmoudle
testbench.v
`timescale 1ns/1ns
module uart_byte_tx_tb():
reg clk;
reg reset_n;
reg [7:0]data;
reg send_en;
reg [2:0]baud_set;
reg uart_tx;
reg tx_done;
uart_byte_tx uart_byte_tx(
.clk(clk),
.resnet(resnet),
.data(data),
.send_en(send_en),
.baud_set(baud_set),
.uart_tx(uart_tx),
.tx_done(tx_done)
)
initial clk = 1;
always #10 clk = ~clk;
initial begin
reset = 0;
data = 0;
send_en = 0;
baud_set = 4;
#201; // 为什么是201 不是200
#100;
data = 8'h57;
send_en = 1;
#20;
@(posedge tx_done); // 阻塞语句 一直等待直到完成
#20000;
data = 8'h57;
send_en = 1;
#20;
@(posedge tx_done); // 阻塞语句 一直等待直到完成
#20000;
$stop;
endmodule
出了bug,开始调试
问题1:reset = 0
reset一直没有拉高,修改代码
reset = 0;
data = 0;
send_en = 0;
baud_set = 4;
#201; // 为什么是201 不是200
#100;
改为:
reset = 0;
data = 0;
send_en = 0;
baud_set = 4;
#201; // 为什么是201 不是200
reset = 1; // 添加
#100;
问题2:uart_tx = 0
当我们发送send en之后等了一位才发送数据。应该是bps cnt等于0,就发送起始位。。发现的bug,就是bps cnt 没有即使清零,修改为:
在修改send en 为1 的时候 bps cnt为0,要加begin end,有多行的if else,记住
还有个问题 uart tx信号,空闲的时候为高电平
当 bps cnt为0 的时候才为0,bsp cnt空闲的时候为0的状态,又命中了case里面的0.
修改为:
需要避开这个0,用1 起始就可以。
还有个问题没解决,当开始send en为高电平的时候,延迟了一个位
为什么这么久才发送一个起始位。
由于send en开始之后,bps cnt需要从0 才开始是计数。修改为
计满才加1,我现在改成1,就立马发送起始位了
现在还有很多细节没有验证,大致的宏观波形没有问题。
一位的时间是 8.68us,所以波特率一位的时间,没有问题。
体现bps clk
用的地方:
12个分成了11段!多出来了一段。数据位多了一位。
很多人认为写到这个地方就结束了。大多数也是结束了
相关文章
- 实用网站分享:全栈开发可能需要用到的网站
- 【Ubuntu】分布式训练/pycharm远程开发
- 混合开发(Hybrid App)有哪些优劣点?
- 12个 Typescript 开发实用技巧清单
- 2023 年的 12 个加密货币预测 DAPP系统开发
- vue.js客服系统实时聊天项目开发(二十二)vue项目中router.js路由介绍
- 项目开发总结报告【列文】2022.5.12
- [android] 采用pull解析xml文件详解手机开发
- 第一次通过AVD Manager创建了一个虚拟设备,但是在Android Studio运行程序时却无设备可选详解手机开发
- 微服务开发的12项要素详解编程语言
- 深耕Linux,谱写未来开发新篇章(linux开发方向)
- MySQL数据库应用程序开发:挑战与机遇(mysql数据库应用开发)
- 谷歌正在为Android 12原生版开发单手模式 照顾某些小型安卓设备制造商
- 日本科学家开发“声学镊子” 只用声波就能“搬运”小球
- 开发Linux分支开发:走向多元化(linux的分支)
- Oracle时光匆匆,岁月如梭:回顾数据库开发二十年(oracle时间年)
- 大厂研发备受关注的Redis(大厂开发redis)
- 开发跨浏览器javascript常见注意事项