FPGA(5) UART_drive代码

主要思想还是时间并行,以及大计数周期的概念。

module  rs232_diver_RX(sys_clk,sys_rst,RX,data_RX1,data_flag);

    input   sys_clk,sys_rst;//系统时钟,系统复位
    input   RX;   //数据接受

    output  data_RX1;
    output  data_flag;
    reg     [7:0]   data_RX1;//表示接受的数据(总线)
    reg     [7:0]   data_RX;
    reg             data_flag;//表示数据接收到了

/*设置波特率*/
parameter   Baud_MAX=15'd5208;      //9600Baud

    reg  [14:0]   cnt_Baud;  //波特计数,用于产生波特率

    reg               RX_reg1;    //防止亚稳态
    reg               RX_reg2;    //防止亚稳态
    reg               RX_reg3;
    reg               Baud_clk;     //用于数据读取标志(这里设置码元1/4-1/2位置,这里1/4位置)(Buad_MAX/4-1)
    reg               Baud_flag;    //用于数据位数计数,使能,开始标志等(这里设置在码元中间位置)(Baud_MAX/2-1)
    
    reg     [3:0]     Baud_num;     //用于记录一个数据经历几个sys_flag
    reg               start_flag;  //当接受高电平时,在sys_clk立刻置为,这时立刻同步波特计数
    reg               RX_enable;    //表示数据有效状态


/* 防止亚稳态(注意默认接受为高电平,低电平表示启动) */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        RX_reg1<=1'b1;
    else
        RX_reg1<=RX;
end
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        RX_reg2<=1'b1;
    else
        RX_reg2<=RX_reg1;
end
always@(posedge sys_clk or negedge sys_rst)
begin
    if(!sys_rst)
        RX_reg3 <= 1'b1;
    else
        RX_reg3 <= RX_reg2;
end
//start_flag:检测到下降沿时start_flag产生一个时钟的高电平
always@(posedge sys_clk or negedge sys_rst)
begin
    if(!sys_rst)
        start_flag <= 1'b0;
    else    if((~RX_reg2) && (RX_reg3)&&(RX_enable==1'b0))
        start_flag <= 1'b1;
    else
        start_flag <= 1'b0;
end

/* RX_enable信号 */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        RX_enable<=1'b0;
    else    if(start_flag==1'b1)
        RX_enable<=1'b1;
    else    if((Baud_num==4'd9)&&(Baud_flag==1'b1))//----------------------------------------
        RX_enable<=1'b0;
    else
        RX_enable<=RX_enable;
end
/* 波特计数,产生”码元长度“,为后面分别在1/2码元长度产生Baud_flag,和1/4码元产生baud_clk */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        cnt_Baud<=15'd0;
    else    if((cnt_Baud==Baud_MAX-1)||(start_flag==1'b1))
        cnt_Baud<=15'd0;
    else
        cnt_Baud<=cnt_Baud+1'b1;
end
/* 产生Baud_flag */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        Baud_flag<=1'b0;
    else    if(cnt_Baud==Baud_MAX/2-1)
        Baud_flag<=1'b1;
    else
        Baud_flag<=1'b0;
end
/* 产生Baud_clk */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        Baud_clk<=1'b0;
    else    if(cnt_Baud==Baud_MAX*3/4)
        Baud_clk<=1'b1;
    else
        Baud_clk<=1'b0;
end

/* 产生Baud_num */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        Baud_num<=4'd0;
    else    if(RX_enable==1'b0)     Baud_num<=4'd0;
    else    if((RX_enable==1'b1)&&(Baud_flag==1'b1))
        Baud_num<=Baud_num+1'b1;
    else
        Baud_num<=Baud_num;
end

/* 最后一步,根据Baud_num和into_reg2进行数据的合并 */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        data_RX<=8'b1111_1111;
    else    if((Baud_clk==1'b1)&&(RX_enable==1'b1))
        begin
            case(Baud_num)
        2:  data_RX<={data_RX[7],data_RX[6],data_RX[5],data_RX[4],data_RX[3],data_RX[2],data_RX[1],RX_reg2};
        3:  data_RX<={data_RX[7],data_RX[6],data_RX[5],data_RX[4],data_RX[3],data_RX[2],RX_reg2,data_RX[0]};
        4:  data_RX<={data_RX[7],data_RX[6],data_RX[5],data_RX[4],data_RX[3],RX_reg2,data_RX[1],data_RX[0]};
        5:  data_RX<={data_RX[7],data_RX[6],data_RX[5],data_RX[4],RX_reg2,data_RX[2],data_RX[1],data_RX[0]};
        6:  data_RX<={data_RX[7],data_RX[6],data_RX[5],RX_reg2,data_RX[3],data_RX[2],data_RX[1],data_RX[0]};
        7:  data_RX<={data_RX[7],data_RX[6],RX_reg2,data_RX[4],data_RX[3],data_RX[2],data_RX[1],data_RX[0]};
        8:  data_RX<={data_RX[7],RX_reg2,data_RX[5],data_RX[4],data_RX[3],data_RX[2],data_RX[1],data_RX[0]};
        9:  data_RX<={RX_reg2,data_RX[6],data_RX[5],data_RX[4],data_RX[3],data_RX[2],data_RX[1],data_RX[0]};
        default:    data_RX<=data_RX;
            endcase
        end
    else
        data_RX<=data_RX;
end

/* 最后一步,产生data_flag用于其他模块,表示已经接收到数据,最后这里一般会存到RAM中,或者FiFo */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)begin
        data_flag<=1'b0;
        data_RX1<=8'b1111_0000;
        end
    else    if((Baud_flag==1'b1)&&(Baud_num==4'd9))begin
        data_RX1<=data_RX;
        data_flag<=1'b1;
        end
    else
        data_flag<=1'b0;
end


endmodule
module  rs232_diver_TX(sys_clk,sys_rst,TX_data1,TX_dataStart,TX_out1);

    input   sys_clk,sys_rst;//系统时钟,复位
    input   wire    [7:0]   TX_data1;//表示要发送的数据
    input   wire            TX_dataStart;//表示数据发送开始标志位

    output  reg            TX_out1;//表示数据输出

parameter   Baud_MAX=15'd5209;//波特率设置(50_000_000/波特率)

    reg             TX_out;//防止亚稳态
    reg   [7:0]    TX_data;//暂存该数据

    reg    [14:0]   cnt_Baud;
    reg             Baud_clk;
    reg     [4:0]   state;
    reg     [4:0]   state_num;
    reg             TX_enable;


always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        cnt_Baud<=15'd0;
    else    if((cnt_Baud==Baud_MAX)||(TX_dataStart==1'b1))//产生码元同步
        cnt_Baud<=15'd0;
    else
        cnt_Baud<=cnt_Baud+1'b1;
end

/* 产生baud_clk信号 */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        Baud_clk<=1'b0;
    else    if((cnt_Baud==Baud_MAX-1))//产生码元同步
        Baud_clk<=1'b1;
    else
        Baud_clk<=1'b0;
end
/* 产生TX_enable信号 */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        TX_enable<=1'b0;
    else    if((TX_dataStart==1'b1)&&(TX_enable==1'b0))
        TX_enable<=1'b1;
    else    if((state_num==4'd10)&&(TX_enable==1'b1)&&(cnt_Baud==Baud_MAX/2))
        TX_enable<=1'b0;
    else
        TX_enable<=TX_enable;
end

/* 产生state_num信号 */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        state_num<=4'd0;
    else    if(TX_enable==1'b0)     state_num<=4'd0;
    else    if((cnt_Baud==Baud_MAX/2)&&(TX_enable==1'b1))
        state_num<=state_num+1'b1;
    else
        state_num<=state_num;
end

/* 执行串行输出 */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        TX_out<=1'b1;
    else    if((TX_enable==1'b1)&&(Baud_clk==1'b1))
            begin
                case(state_num)
                0:TX_out<=1'b1;
                1:TX_out<=1'b0;
                2:TX_out<=TX_data[0];
                3:TX_out<=TX_data[1];
                4:TX_out<=TX_data[2];
                5:TX_out<=TX_data[3];
                6:TX_out<=TX_data[4];
                7:TX_out<=TX_data[5];
                8:TX_out<=TX_data[6];
                9:TX_out<=TX_data[7];
                10: TX_out<=1'b1;
            default:    TX_out<=1'b1;
                endcase
end
                
end

/* 以下缓存 */
always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        TX_out1<=1'b1;
    else  
        TX_out1<=TX_out;
end

always@(posedge sys_clk or negedge  sys_rst)
begin
    if(!sys_rst)
        TX_data<=8'hff;
    else    if(TX_dataStart==1'b1)
        TX_data<=TX_data1;
    else
        TX_data<=TX_data;
end

endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦灵-影

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值