verilog基础---uart_rx代码
1、功能概述
功能是接收串口,波特率是115200,时钟是148.5Mhz。
控制的参数:
顶层接口:
clk | 148.5M |
Rst_n | 低电平复位 |
rx_data | 串口接收的数据 |
rs232_rx | 串口的tx引脚线 |
rx_dvalid | 1表示rx_data数据有效 |
转载:https://blog.csdn.net/weixin_36590806/article/details/118441673
思路:
设计两个模块,一个模块是根据时钟控制读写的时间点。
另一个模块是接收串口的模块。
顶层模块的代码:
module my_uart_rx_top
(
input clk , //148.5M
input rst_n ,
input rs232_rx ,
output rx_dvalid ,
output [7:0]rx_data
);
wire bps_start ;
wire clk_bps1 ;
speed_select speed_rx_inst
(
.clk ( clk ), //波特率选择模块
.rst_n ( rst_n ),
.bps_start( bps_start ),
.clk_bps ( clk_bps1 )
);
my_uart_rx my_uart_rx_inst
(
.clk ( clk ), //接收数据模块
.rst_n ( rst_n ),
.rs232_rx ( rs232_rx ),
.rx_data ( rx_data ),
.rx_int ( rx_dvalid ),
.clk_bps ( clk_bps1 ),
.bps_start( bps_start )
);
endmodule
speed_select模块代码:
module speed_select
(
clk ,
rst_n ,
bps_start,
clk_bps
);
input clk ; // 148.5MHz主时钟
input rst_n ; //低电平复位信号
input bps_start; //接收到数据后,波特率时钟启动信号置位
output clk_bps ; // clk_bps的高电平为接收或者发送数据位的中间采样点
parameter bps115200 = 1288 ; //148.5MHZ 波特率为115200bps
parameter bps115200_2 = 644 ;
reg[13:0] cnt ; //分频计数
reg clk_bps_r; //波特率时钟寄存器
//----------------------------------------------------------
always @ (posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 14'd0;
else if((cnt >= bps115200) || !bps_start)
cnt <= 14'd0; //波特率计数清零
else
cnt <= cnt+1'b1;//波特率时钟计数启动
always @ (posedge clk or negedge rst_n)
if(!rst_n)
clk_bps_r <= 1'b0;
else if(cnt == bps115200_2)
clk_bps_r <= 1'b1;
else
clk_bps_r <= 1'b0;
assign clk_bps = clk_bps_r;
endmodule
my_uart_rx模块的代码:
module my_uart_rx(
clk ,
rst_n ,
rs232_rx ,
rx_data ,
rx_int ,
clk_bps ,
bps_start
);
input clk ; // 148.5MHz主时钟
input rst_n ; //低电平复位信号
input rs232_rx ; // RS232接收数据信号
input clk_bps ; // clk_bps的高电平为接收或者发送数据位的中间采样点
output bps_start ; //接收到数据后,波特率时钟启动信号置位
output[7:0] rx_data; //接收数据寄存器,保存直至下一个数据来到
output rx_int ; //接收数据中断信号,接收到数据期间始终为高电平
//----------------------------------------------------------------
reg rs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3,rs232_rx4; //接收数据寄存器,滤波用
wire neg_rs232_rx; //表示数据线接收到下降沿
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
rs232_rx0 <= 1'b0;
rs232_rx1 <= 1'b0;
rs232_rx2 <= 1'b0;
rs232_rx3 <= 1'b0;
rs232_rx4 <= 1'b0;
end
else begin
rs232_rx0 <= rs232_rx ;
rs232_rx1 <= rs232_rx0;
rs232_rx2 <= rs232_rx1;
if(rs232_rx1&&rs232_rx2)
rs232_rx3 <= 1'b1;
else if(~(rs232_rx1||rs232_rx2))
rs232_rx3 <= 1'b0;
else
rs232_rx3 <= rs232_rx3;
rs232_rx4 <= rs232_rx3;
end
end
//下降沿检测
assign neg_rs232_rx = rs232_rx4 & (~rs232_rx3); //接收到下降沿后neg_rs232_rx置高一个时钟周期
//----------------------------------------------------------------
reg bps_start_r;
reg[3:0] num; //移位次数
reg rx_int; //接收数据中断信号,接收到数据期间始终为高电平
reg start_bit_check ; //起始位错误标志
always@(posedge clk,negedge rst_n)
if(~rst_n)
start_bit_check <= 1'b0 ;
else
start_bit_check <= clk_bps && (num == 4'd0) && rs232_rx3 ;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
bps_start_r <= 1'b0;
else if(neg_rs232_rx) //接收到串口接收线rs232_rx的下降沿标志信号
bps_start_r <= 1'b1; //启动串口准备数据接收
else if(start_bit_check)//检测到起始位错误
bps_start_r <= 1'b0 ;
else if(num==4'd9) //接收完有用数据信息
bps_start_r <= 1'b0 ; //数据接收完毕,释放波特率启动信号
assign bps_start = bps_start_r;
//----------------------------------------------------------------
reg[7:0] rx_data_r; //串口接收数据寄存器,保存直至下一个数据来到
//----------------------------------------------------------------
reg[7:0] rx_temp_data; //当前接收数据寄存器
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
rx_temp_data <= 8'd0 ;
num <= 4'd0 ;
rx_data_r <= 8'd0 ;
rx_int <= 1'b0 ;
end
else if(start_bit_check)begin
num <= 4'd0 ;
rx_int <= 1'b0 ;
end
else if(bps_start_r) begin //接收数据处理
if(clk_bps) begin //读取并保存数据,接收数据为一个起始位,8bit数据,1或2个结束位
num <= num+1'b1;
case (num)
4'd1: rx_temp_data[0] <= rs232_rx3; //锁存第0bit
4'd2: rx_temp_data[1] <= rs232_rx3; //锁存第1bit
4'd3: rx_temp_data[2] <= rs232_rx3; //锁存第2bit
4'd4: rx_temp_data[3] <= rs232_rx3; //锁存第3bit
4'd5: rx_temp_data[4] <= rs232_rx3; //锁存第4bit
4'd6: rx_temp_data[5] <= rs232_rx3; //锁存第5bit
4'd7: rx_temp_data[6] <= rs232_rx3; //锁存第6bit
4'd8: rx_temp_data[7] <= rs232_rx3; //锁存第7bit
default:;
endcase
end
else if(num == 4'd9) begin //我们的标准接收模式下只有1+8+1(2)=11bit的有效数据
rx_int <= 1'b1 ;
num <= 4'd0 ; //接收到STOP位后结束,num清零
rx_data_r <= rx_temp_data; //把数据锁存到数据寄存器rx_data中
end
end
else begin
rx_int <= 1'b0 ;
num <= 4'd0 ;
end
assign rx_data = rx_data_r;
endmodule
如果细心的朋友可以看到这里的speed_select和tx篇中的是一样的。所以在设计代码时,可以使用一个就可以了。
相关文章
- javaWeb学习总结(8)- JSP基础语法(2)
- 个人零基础搭建WordPress博客站点,并发布公网访问 8-10
- koa 基础(九) ejs 模板引擎的使用
- FPGA工程师面试——基础概念问题整理
- C#,精巧实用的代码,生成机器码(Machine Id)的基础源代码
- OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例》一6.3 定位光与定向光
- 重构·改善既有代码的设计.01之入门基础
- Python基础必掌握的利用Booleans优化代码巧妙方法
- SwiftUI AppStorage 基础使用(教程含代码)
- SwiftUI机器学习入门之基础概念和万物识别App
- SwiftUI 基础之@ObservedObject 有什么用(含demo代码2020)
- JNI入门课程-第二章:JNI基础调用
- 【Vue】vue基础语法——自定义指令、过滤、组件和动画(内附详细案例代码)——day04
- 【校招Verilog快速入门】基础语法篇:VL8、使用generate…for语句简化代码
- 【Verilog基础】编写 RTL 代码时推荐的一些规范
- verilog基础---uart_tx代码
- Visual Studio 基础 之 VS 查看/反编译 C# dll 脚本代码的简单方法
- IntellJ IDEA 基础之 一些常用插件plugin 简单整理 (辅助提高编写代码效率)
- 《C#零基础入门之百识百例》(八十三)系统类ArrayList数组列表详解 -- 代码示例
- (2.11)Mysql之SQL基础——存储过程与变量及动态SQL
- 开源博客QBlog开发者视频教程:开篇-开发基础配置与系统运行(一)
- Java多线程基础(一)---Thread API(join深度详解、源码分析和案例分析之代码实现,优雅关闭线程三种方式)
- 《Linux命令行与shell脚本编程大全 第3版》Shell脚本编程基础---07
- CRMEB 基础 切换标签页后 关闭之前的标签页