完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
|
新手刚学FPGA遇到的一个疑惑,如下文橙色代码的所示,发送模块和接受模块都在中间采样点收数或者发数,收数我倒是好理解,因为中间时刻的值最稳定,所以在中间时刻进行收数采样,但是发数为什么也得在中间时刻到达后才进行呢?而且我实验了一下,发现去掉always @ (posedge clk or negedge rst_n)
if(!rst_n) clk_bps_r <= 1'b0; else if(cnt == `BPS_PARA_2) clk_bps_r <= 1'b1; else clk_bps_r <= 1'b0;这个语句(即只要达到tx_en=1就执行发数,不必达到cnt == `BPS_PARA_2),但是这样串口就不好使了,但是我不知道, else if(cnt == `BPS_PARA_2) clk_bps_r <= 1'b1; 然后再 执行 else if(tx_en) begin if(clk_bps) begin num <= num+1'b1; case (num) 这样的作用是什么? 希望能有人给我耐心解决一下,感激不尽代码如下 波特率设置模块: ///////////////////////////////////////////////////////////// module speed_select( clk,rst_n, bps_start,clk_bps ); input clk; // 50MHz主时钟 input rst_n; //低电平复位信号 input bps_start; //接收到数据后,波特率时钟启动信号置位 output clk_bps; // clk_bps的高电平为接收或者发送数据位的中间采样点 `define BPS_PARA 5207 //波特率为9600时的分频计数值 `define BPS_PARA_2 2603 //波特率为9600时的分频计数值的一半,用于数据采样 reg[12:0] cnt; //分频计数 reg clk_bps_r; //波特率时钟寄存器 //---------------------------------------------------------- reg[2:0] uart_ctrl; // uart波特率选择寄存器 //---------------------------------------------------------- always @ (posedge clk or negedge rst_n) if(!rst_n) cnt <= 13'd0; else if((cnt == `BPS_PARA) || !bps_start) cnt <= 13'd0; //波特率计数清零 else cnt <= cnt+1'b1; //波特率时钟计数启动 always @ (posedge clk or negedge rst_n) if(!rst_n) clk_bps_r <= 1'b0; else if(cnt == `BPS_PARA_2) clk_bps_r <= 1'b1; // clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点 else clk_bps_r <= 1'b0; assign clk_bps = clk_bps_r; endmodule ////////////////////////////////////////////////////////////////////////// 串口发送模块: //////////////////////////////////////////////////////////////////////////// module my_uart_tx( clk,rst_n, rx_data,rx_int,rs232_tx,key, clk_bps,bps_start ); input clk; // 50MHz主时钟 input rst_n; //低电平复位信号 input clk_bps; // clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点 input[7:0] rx_data; //接收数据寄存器 input rx_int; //接收数据中断信号,接收到数据期间始终为高电平,在该模块中利用它的下降沿来启动串口发送数据 input key; output rs232_tx; // RS232发送数据信号 output bps_start; //接收或者要发送数据,波特率时钟启动信号置位 //--------------------------------------------------------- reg rx_int0,rx_int1,rx_int2; //rx_int信号寄存器,捕捉下降沿滤波用 wire neg_rx_int; // rx_int下降沿标志位 always @ (posedge clk or negedge rst_n) begin if(!rst_n) begin rx_int0 <= 1'b0; rx_int1 <= 1'b0; rx_int2 <= 1'b0; end else begin rx_int0 <= rx_int; rx_int1 <= rx_int0; rx_int2 <= rx_int1; end end assign neg_rx_int = ~rx_int1 & rx_int2; //捕捉到下降沿后,neg_rx_int拉高保持一个主时钟周期 //--------------------------------------------------------- reg[7:0] tx_data; //待发送数据的寄存器 //--------------------------------------------------------- reg bps_start_r; reg tx_en; //发送数据使能信号,高有效 reg[3:0] num; always @ (posedge clk or negedge rst_n) begin if(!rst_n) begin bps_start_r <= 1'b0; tx_en <= 1'b0; tx_data <= 8'd0; end else if(neg_rx_int) begin //接收数据完毕,准备把接收到的数据发回去 bps_start_r <= 1'b1; tx_data <= rx_data; //把接收到的数据存入发送数据寄存器 tx_en <= 1'b1; //进入发送数据状态中 end else if(num==4'd10) begin //数据发送完成,复位 bps_start_r <= 1'b0; tx_en <= 1'b0; end end assign bps_start = bps_start_r;//接收或者要发送数据,波特率时钟启动信号置位 //--------------------------------------------------------- reg rs232_tx_r; always @ (posedge clk or negedge rst_n) begin if(!rst_n) begin num <= 4'd0; rs232_tx_r <= 1'b1; end else if(tx_en) begin if(clk_bps) begin num <= num+1'b1;//对发送进行计数 case (num) 4'd0: rs232_tx_r <= 1'b0; //发送起始位 4'd1: rs232_tx_r <= tx_data[0]; //发送bit0 4'd2: rs232_tx_r <= tx_data[1]; //发送bit1 4'd3: rs232_tx_r <= tx_data[2]; //发送bit2 4'd4: rs232_tx_r <= tx_data[3]; //发送bit3 4'd5: rs232_tx_r <= tx_data[4]; //发送bit4 4'd6: rs232_tx_r <= tx_data[5]; //发送bit5 4'd7: rs232_tx_r <= tx_data[6]; //发送bit6 4'd8: rs232_tx_r <= tx_data[7]; //发送bit7 4'd9: rs232_tx_r <= 1'b1; //发送结束位 default: rs232_tx_r <= 1'b1; endcase end else if(num==4'd10) num <= 4'd0; //复位 end end |
|
相关推荐
4个回答
|
|
|
我也刚开始学,也看特权同学的书,谈下我的理解,我存在错误理解也不一定。在这个串口例子中用的是脉冲边沿检测,仅仅是cnt == `BPS_PARA_2(中间部分)时一个脉冲的高电平用于读取状态和计数器加1,如果你纯粹tx_en=1就相当于检测到脉冲后的9个时钟节拍就已经把数据发完了,那当然不行了。主要注意的是原程序是一个时钟的高电平,而你改后可能就是持续高电平,你仿真一下就会发现计数器出问题了。
|
|
|
|
|
|
看看!!!!!!
|
|
|
|
|
|
大厦 是是是是是大厦是是发
|
|
|
|
|
|
clk_bps是波特率时钟,收发数据实质上都是按照这个速率执行的,每一个clk_bps时钟周期收一个或者发一个bit数据,tx_en拉高意思是数据已经放到发寄存器了,可以准备发送,而这个待发送数据有8bit,加上起始位和终止位总共10bit,每一次tx_en变高时,每当clk_bps变高一次发一个bit,直到发完10bit也就是clk_bps走过10个周期才算发送完一个数据,当然不能只看tx_en啊,所以一个tx_en对应的是10个clk_bps周期
|
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
NVMe高速传输之摆脱XDMA设计50:主要功能测试结果与分析2 nvmePCIe高速存储
252 浏览 0 评论
NVMe高速传输之摆脱XDMA设计49:主要功能测试结果与分析1
1501 浏览 0 评论
907 浏览 0 评论
855 浏览 0 评论
658 浏览 0 评论
4427 浏览 63 评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-2 21:12 , Processed in 0.927603 second(s), Total 76, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
4755