一个关于特权同学的串口通信代码的问题

2019-07-15 23:39发布

tica, SimSun, sans-serif">新手刚学FPGA遇到的一个疑惑,如下文橙 {MOD}代码的所示,发送模块和接受模块都在中间采样点收数或者发数,收数我倒是好理解,因为中间时刻的值最稳定,所以在中间时刻进行收数采样,但是发数为什么也得在中间时刻到达后才进行呢?而且我实验了一下,发现去掉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条回答
nghe
1楼-- · 2019-07-16 03:21
 精彩回答 2  元偷偷看……
琴声悠扬
2楼-- · 2019-07-16 08:33
看看!!!!!!
师大刘
3楼-- · 2019-07-16 08:49
大厦 是是是是是大厦是是发
runileking
4楼-- · 2019-07-16 12:22
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周期

一周热门 更多>