您的位置:首页 > 博客中心 > 互联网 >

使用UART实现FPGA板与PC通信

时间:2022-05-11 07:24

(一) UART 介绍

略……(后续会补上)

(二) UART 软件

略……(后续会补上)

(三) UART 模块介绍

下面先介绍UART关键的3个模块,可以先不理解其中的工作原理,先了解这几个模块的作用与效果。

/* Uart时钟信号 */
module Uart_ClkDiv(
	input Sys_CLK,  //50Mhz系统时钟
	output Uart_CLK //9600bps
	);

上述Uart_ClkDiv用来生成Uart传输所需要的时钟信号,输入50Mhz系统时钟,输出Uart时钟

/* Uart_Rx 用于接收数据 */
module Uart_Rx(
	input Uart_CLK,//采样时钟
	input RST,//复位信号
	input Signal_Rx,//UART数据输入

	output reg [7:0] Data_Rx,//接收数据输出
	output reg Rdsig,//置1时表示上层模块已经可以读8位数据了
	output reg DataError_Flag,//数据出错指示
	output reg FrameError_Flag//帧出错指示
	);

上述Uart_Rx用于接收数据,输入的Uart_CLK为模块Uart_ClkDiv生成的Uart时钟信号,RST为复位键信号(低电平有效),Signal_Rx为Uart数据输入信号
8bit输出Data_Rx为一次接收获取的数据,Rdsig为低电平表示正在接收数据,当一次数据接收完毕后会置成一段时间的高电平
DataError_Flag和FrameError_Flag都是出错提示,当接收数据过程发送错误会被置成高电平,需要注意此处的校验位为偶校验位(Even)

/* Uart_Tx发送数据 */
module Uart_Tx(
    input Uart_CLK,
    input RST,
    input [7:0] Data_Tx,//8位待发送数据
    input Wrsig,
    output reg Idle,//空闲状态,0表示空闲,1表示忙碌
    output reg Signal_Tx//并转串,1位输出
    );

上述Uart_Tx用于发送数据,输入的Uart_CLK为模块Uart_ClkDiv生成的Uart时钟信号,RST为复位键信号(低电平有效)
Data_Tx为8bit待发送数据,Wrsig上升沿时开始发送
Idle是Uart_Tx发送器的状态,0表示空闲,1表示忙碌, Signal_Tx是数据输出信号
上述三个模块是UART发送的核心,但要实现超过8位的数据传输,单靠上面还不够

(四) 实现多比特数据传输

由于UART的资料位(数据位)一般是8位,但实际应用中需要传输多位数据。根据Uart_Rx和Uart_Tx各接口的效果,使用时钟周期进行循环接收与发送
此处以接收64bit数据,并将接收到的数据发送为例,演示多位数据传输的原理
技术图片
注意:图中的校验位为EVEN,应该为偶校验,猜测软件将EVEN(偶)标记成EVEN(奇)

/* 顶层模块 */
module uart_top(
    input sys_clk,//系统时钟
    input sys_rst,//复位键
    input signal_rx,//接收信号rx
    input enable,//使能信号

    output isEnable,//是否能够运行
    output Err,//错误信号
    output busy,//忙碌信号
    output finish,//完成信号
    output signal_tx//tx发送信号
    );

上述为顶层模块的接口,由于代码实现的原因,在每次发送数据至 FPGA 板子前需要按下复位键,否则将无法正常接收
运行中信号,错误信号,忙碌信号,完成信号分别绑在FPGA的4个LED灯中,作为FPGA传输数据时的反馈
使能信号enable绑于一个拨码开关上,高电平运行

/* 循环接收模块 */
module Uart_Receive_Top(
    input sys_clk,//系统时钟
    input sys_rst,//系统复位键
    input signal_rx,//接收信号rx
    input enable,//使能信号

    output reg[63:0] data_input,//数据输入
    output reg Err,//报错,高电平出错
    output reg finish,//接收完成信号
    output reg busy//高电平忙碌
    );

上述是接收模块的接口定义,在此模块中实现循环接收数据,接收完毕后会将finish信号置1,表示接收完成
如果接收未完成,busy信号为1,如果接收出错,Err信号为1

      /* 循环接收模块 */
      case(state)
      4‘d00 : begin
            if(Rdsig && !DataError && !FrameError) begin
                  data_input[64-0*8-1:64-(0+1)*8] <= data_rx;
                  busy <= 1‘b1; 
                  state <= state + 1;	
            end
            else if(DataError || FrameError) begin
                  Err <= 1;
                  state <= 4‘b1111;
            end
      end
      4‘d01 : begin
            if(!Rdsig)state <= state + 1;
      end
      4‘d02 : begin
            if(Rdsig && !DataError && !FrameError) begin
                  data_input[64-1*8-1:64-(1+1)*8] <= data_rx;
                  busy <= 1‘b1; 
                  state <= state + 1;	
            end
            else if(DataError || FrameError) begin
                  Err <= 1;
                  state <= 4‘b1111;
            end
      end
      4‘d03 : begin
            if(!Rdsig)state <= state + 1;
      end
      ...
      4‘d14 : begin
            if(Rdsig && !DataError && !FrameError) begin
                  data_input[64-7*8-1:64-(7+1)*8] <= data_rx;
                  finish <= 1;
                  busy <= 0;
                  state <= state;	
            end
            else if(DataError || FrameError) begin
                  Err <= 1;
                  state <= 4‘b1111;
            end
      end
      //报错
      4‘b1111:Err<=1;
      default:;
      endcase

上述是接收过程的其中几个状态,每两个状态完成一次接收操作
第一个状态进行接收,当Rwsig为1是表示接收完毕,DataError和FrameError都不为0表示未发生错误
故一次接收完成,进行data_input的赋值,并让state + 1跳转至下一个状态;如果发生错误,将状态跳转到报错状态
第二个状态等待下一次接收的开始,当Rwsig为0后表明接收开始,跳转到下一个状态等待接收完毕
当最后一个数据接收完毕后,将finish置1,busy置0,表明接收完毕

module Uart_Send_Top(
    input sys_clk,//系统时钟50MHz 
    input sys_rst,//重置键rst 
    input [63:0] data_output,//待发送数据
    input enable,//发送使能,1为可以发送

    output wire signal_tx,//uart发送信号tx
    output reg Err,//报错,高电平出错 
    output reg finish,//完成信号
    output reg busy//高电平时表示忙碌
    );

上述是循环发送模块的接口定义,与接收接口类似

      /* 循环发送模块 */
      case(state)
      4‘d00 : begin
            if(!Busy_Tx) begin
                  Data_Tx <= data_output[64-0*8-1:64-(0+1)*8];
                  Wrsig <= 1; 
                  state <= state + 1;
                  wait_cnt <= 12‘d0;
                  wait_finished <= 1‘b0;
            end
      end
      4‘d01 : begin
            if(Busy_Tx) begin
                  Wrsig <= 0;
            end
            else begin
                  wait_cnt <= wait_cnt + 1;
                  if(wait_cnt == 12‘hA00) begin
                        wait_cnt <= 12‘d0;
                        wait_finished <= 1‘b1;
                  end
                  else if(wait_cnt == 12‘d0 && wait_finished) state <= state + 1;
            end
      end
      4‘d02 : begin
            if(!Busy_Tx) begin
                  Data_Tx <= data_output[64-1*8-1:64-(1+1)*8];
                  Wrsig <= 1; 
                  state <= state + 1;
                  wait_cnt <= 12‘d0;
                  wait_finished <= 1‘b0;
            end
      end
      4‘d03 : begin
            if(Busy_Tx) begin
                  Wrsig <= 0;
            end
            else begin
                  wait_cnt <= wait_cnt + 1;
                  if(wait_cnt == 12‘hA00) begin
                        wait_cnt <= 12‘d0;
                        wait_finished <= 1‘b1;
                  end
            else if(wait_cnt == 12‘d0 && wait_finished) state <= state + 1;
      end
      ...
      4‘d14 : begin
            if(!Busy_Tx) begin
                  Data_Tx <= data_output[64-7*8-1:64-(7+1)*8];
                  Wrsig <= 1; 
                  state <= state + 1;
                  wait_cnt <= 12‘d0;
                  wait_finished <= 1‘b0;
            end
      end
      4‘d15 : begin
            if(Busy_Tx) begin
                  Wrsig <= 0;
            end
            else begin
                  wait_cnt <= wait_cnt + 1;
                  if(wait_cnt == 12‘hA00) begin
                        wait_cnt <= 12‘d0;
                        wait_finished <= 1‘b1;
                  end
                  else if(wait_cnt == 12‘d0 && wait_finished) begin//发送完成
                        finish <= 1;
                        busy <= 0;
                  end
            end
      end
      default:;
      endcase

上述是发送过程的几个状态,同接收类似,每两个状态完成一次发送
第一个状态是发送数据,当Busy_Tx为0,即发送器空闲时,传入发送数据,并产生Wrsig高电平启动信号
设置wait_cnt的原因是两次发送最好有一个码元的间隔,当传输发送数据后,wait_cnt和wait_finished都置0,开始计数,并跳转到下一个状态
第二个状态等待将Wrsig置回0,完成一次启动信号的发生;当传输完毕,发送器变回空闲状态(Busy_Tx=0)时,开始计数
计数完毕后,跳转至下一个状态
最后一个状态结束后不再跳转,将finish置成1,busy置成0,其他保持不变

通过上述两个循环,完成对数据的接收与发送

(五) ISE综合

综合过程中可能会出现如下warning,这是由于我们使用了Uart_CLK代替了系统时钟,会产生警告(可忽略)

Route:455 - CLK Net:Uart_Send_Top/module_ClkDiv/Uart_CLK may have excessive skew

引脚定义如下
技术图片

(六) 完整代码

uart_top.v

module uart_top(
    input sys_clk,//系统时钟
    input sys_rst,//复位键
    input signal_rx,//接收信号rx
    input enable,//使能信号

    output isEnable,//是否能够运行
    output Err,//错误信号
    output busy,//忙碌信号
    output finish,//完成信号
    output signal_tx//tx发送信号
    );

    wire [63:0] data;
    wire finish_receive;

    /* uart接收 */
    wire err_rx;
    wire busy_rx;
    Uart_Receive_Top Uart_Receive_Top(
        .sys_clk(sys_clk),
        .sys_rst(sys_rst),
        .signal_rx(signal_rx),
        .enable(enable),

        .data_input(data),
        .Err(err_rx),
        .busy(busy_rx),
        .finish(finish_receive)
    );

    /* uart发送 */
    wire err_tx;
    wire busy_tx;
    Uart_Send_Top Uart_Send_Top(
        .sys_clk(sys_clk),
        .sys_rst(sys_rst),
        .data_output(data),
        .enable(finish_receive),

        .signal_tx(signal_tx),
        .Err(err_tx),
        .finish(finish),
        .busy(busy_tx)
    );

    assign busy = busy_rx | busy_tx ;
    assign Err = err_rx | err_tx;
    assign isEnable = enable;
endmodule

Uart_Receive_Top.v

module Uart_Receive_Top(
    input sys_clk,//系统时钟
    input sys_rst,//系统复位键
    input signal_rx,//接收信号rx
    input enable,//使能信号

    output reg[63:0] data_input,//加解密文输入
    output reg Err,//报错,高电平出错
    output reg finish,//接收完成信号
    output reg busy//高电平忙碌
    );

    /* uart时钟信号产生 */
    wire uart_clk;
    Uart_ClkDiv module_ClkDiv(
        .Sys_CLK(sys_clk),
        .Uart_CLK(uart_clk)
    );


    /* 接收模块 */
    wire[7:0] data_rx;//接收数据缓存
    wire Rdsig;//读使能,高电平时可以从8位缓存中读取数据
    wire DataError;//数据错误信号,高电平时出错
    wire FrameError;//帧错误信号,高电平时出错

    Uart_Rx module_Rx(
        .Uart_CLK(uart_clk),
        .RST(sys_rst),
        .Signal_Rx(signal_rx),

        .Data_Rx(data_rx),
        .Rdsig(Rdsig),
        .DataError_Flag(DataError),
        .FrameError_Flag(FrameError)
    );

    /* 状态机 */
    reg [3:0] state;

    always@(posedge sys_clk or negedge sys_rst) begin
        if(~sys_rst) begin
            Err <= 0;
            finish <= 0;
            busy <= 0;
            data_input <= 64‘b0;
            state <= 4‘b0;
        end
        else if(~enable) begin
            Err <= 0;
            finish <= 0;
            busy <= 0;
            data_input <= 64‘b0;
            state <= 4‘b0;
        end
        else begin
            case(state)
            //读取64bit 的data_input
            4‘d00 : begin
                if(Rdsig && !DataError && !FrameError)begin
                    data_input[64-0*8-1:64-(0+1)*8] <= data_rx;
                    busy <= 1‘b1; 
                    state <= state + 1;	end
                else if(DataError || FrameError) begin
                    Err <= 1;
                    state <= 4‘b1111;
                end
            end
            4‘d01 : begin
                if(!Rdsig)state <= state + 1;
            end
            4‘d02 : begin
                if(Rdsig && !DataError && !FrameError)begin
                    data_input[64-1*8-1:64-(1+1)*8] <= data_rx;
                    busy <= 1‘b1; 
                    state <= state + 1;	end
                else if(DataError || FrameError) begin
                    Err <= 1;
                    state <= 4‘b1111;
                end
            end
            4‘d03 : begin
                if(!Rdsig)state <= state + 1;
            end
            4‘d04 : begin
                if(Rdsig && !DataError && !FrameError)begin
                    data_input[64-2*8-1:64-(2+1)*8] <= data_rx;
                    busy <= 1‘b1; 
                    state <= state + 1;	end
                else if(DataError || FrameError) begin
                    Err <= 1;
                    state <= 4‘b1111;
                end
            end
            4‘d05 : begin
                if(!Rdsig)state <= state + 1;
            end
            4‘d06 : begin
                if(Rdsig && !DataError && !FrameError)begin
                    data_input[64-3*8-1:64-(3+1)*8] <= data_rx;
                    busy <= 1‘b1; 
                    state <= state + 1;	end
                else if(DataError || FrameError) begin
                    Err <= 1;
                    state <= 4‘b1111;
                end
            end
            4‘d07 : begin
                if(!Rdsig)state <= state + 1;
            end
            4‘d08 : begin
                if(Rdsig && !DataError && !FrameError)begin
                    data_input[64-4*8-1:64-(4+1)*8] <= data_rx;
                    busy <= 1‘b1; 
                    state <= state + 1;	end
                else if(DataError || FrameError) begin
                    Err <= 1;
                    state <= 4‘b1111;
                end
            end
            4‘d09 : begin
                if(!Rdsig)state <= state + 1;
            end
            4‘d10 : begin
                if(Rdsig && !DataError && !FrameError)begin
                    data_input[64-5*8-1:64-(5+1)*8] <= data_rx;
                    busy <= 1‘b1; 
                    state <= state + 1;	end
                else if(DataError || FrameError) begin
                    Err <= 1;
                    state <= 4‘b1111;
                end
            end
            4‘d11 : begin
                if(!Rdsig)state <= state + 1;
            end
            4‘d12 : begin
                if(Rdsig && !DataError && !FrameError)begin
                    data_input[64-6*8-1:64-(6+1)*8] <= data_rx;
                    busy <= 1‘b1; 
                    state <= state + 1;	end
                else if(DataError || FrameError) begin
                    Err <= 1;
                    state <= 4‘b1111;
                end
            end
            4‘d13 : begin
                if(!Rdsig)state <= state + 1;
            end
            4‘d14 : begin
                if(Rdsig && !DataError && !FrameError)begin
                    data_input[64-7*8-1:64-(7+1)*8] <= data_rx;
                    finish <= 1;
                    busy <= 0;
                    state <= state;	
                end
                else if(DataError || FrameError) begin
                    Err <= 1;
                    state <= 4‘b1111;
                end
            end
            //报错
            4‘b1111:Err<=1;
            default:;
            endcase
        end
    end
endmodule

Uart_Send_Top.v

module Uart_Send_Top(
    input sys_clk,//系统时钟50MHz 
    input sys_rst,//重置键rst 
    input [63:0] data_output,//待发送数据
    input enable,//发送使能,1为可以发送

    output wire signal_tx,//uart发送信号tx
    output reg Err,//报错,高电平出错 
    output reg finish,//完成信号
    output reg busy//高电平时表示忙碌
    );

    /* uart时钟信号产生 */
    wire uart_clk;
    Uart_ClkDiv module_ClkDiv(
        .Sys_CLK(sys_clk),
        .Uart_CLK(uart_clk)
    );

    /* 发送模块 */
    reg [7:0] Data_Tx;//待发送8位数据
    reg Wrsig;//写使能,上升沿有效
    wire Busy_Tx;//1时忙碌,0时空闲

    Uart_Tx module_Tx(
        .Uart_CLK(uart_clk),
        .RST(sys_rst),
        .Data_Tx(Data_Tx),
        .Wrsig(Wrsig),

        .Idle(Busy_Tx),
        .Signal_Tx(signal_tx)
    );

    /* 状态机 */
    reg [3:0] state;
    reg[11:0] wait_cnt;//等待时使用的计数器
    reg wait_finished;//1表示完成等待

    always@(posedge sys_clk or negedge sys_rst) begin
        if(~sys_rst) begin
            Err <= 0;
            finish <= 0;
            busy <= 0;
            state <= 4‘b0;
            wait_cnt <= 12‘b0;
            wait_finished <= 0;
            Data_Tx <= 8‘b0;
        end
        else if(~enable) begin
            Err <= 0;
            finish <= 0;
            busy <= 0;
            state <= 4‘b0;
            wait_cnt <= 12‘b0;
            wait_finished <= 0;
            Data_Tx <= 8‘b0;
        end
        else begin
            case(state)
            4‘d00 : begin
                if(!Busy_Tx) begin
                    Data_Tx <= data_output[64-0*8-1:64-(0+1)*8];
                    Wrsig <= 1; 
                    state <= state + 1;
                    wait_cnt <= 12‘d0;
                    wait_finished <= 1‘b0;
                end
            end
            4‘d01 : begin
                if(Busy_Tx) begin
                    Wrsig <= 0;
                end
                else begin
                    wait_cnt <= wait_cnt + 1;
                    if(wait_cnt == 12‘hA00) begin
                        wait_cnt <= 12‘d0;
                        wait_finished <= 1‘b1;
                    end
                    else if(wait_cnt == 12‘d0 && wait_finished) state <= state + 1;
                end
            end
            4‘d02 : begin
                if(!Busy_Tx) begin
                    Data_Tx <= data_output[64-1*8-1:64-(1+1)*8];
                    Wrsig <= 1; 
                    state <= state + 1;
                    wait_cnt <= 12‘d0;
                    wait_finished <= 1‘b0;
                end
            end
            4‘d03 : begin
                if(Busy_Tx) begin
                    Wrsig <= 0;
                end
                else begin
                    wait_cnt <= wait_cnt + 1;
                    if(wait_cnt == 12‘hA00) begin
                        wait_cnt <= 12‘d0;
                        wait_finished <= 1‘b1;
                    end
                    else if(wait_cnt == 12‘d0 && wait_finished) state <= state + 1;
                end
            end
            4‘d04 : begin
                if(!Busy_Tx) begin
                    Data_Tx <= data_output[64-2*8-1:64-(2+1)*8];
                    Wrsig <= 1; 
                    state <= state + 1;
                    wait_cnt <= 12‘d0;
                    wait_finished <= 1‘b0;
                end
            end
            4‘d05 : begin
                if(Busy_Tx) begin
                    Wrsig <= 0;
                end
                else begin
                    wait_cnt <= wait_cnt + 1;
                    if(wait_cnt == 12‘hA00) begin
                        wait_cnt <= 12‘d0;
                        wait_finished <= 1‘b1;
                    end
                    else if(wait_cnt == 12‘d0 && wait_finished) state <= state + 1;
                end
            end
            4‘d06 : begin
                if(!Busy_Tx) begin
                    Data_Tx <= data_output[64-3*8-1:64-(3+1)*8];
                    Wrsig <= 1; 
                    state <= state + 1;
                    wait_cnt <= 12‘d0;
                    wait_finished <= 1‘b0;
                end
            end
            4‘d07 : begin
                if(Busy_Tx) begin
                    Wrsig <= 0;
                end
                else begin
                    wait_cnt <= wait_cnt + 1;
                    if(wait_cnt == 12‘hA00) begin
                        wait_cnt <= 12‘d0;
                        wait_finished <= 1‘b1;
                    end
                    else if(wait_cnt == 12‘d0 && wait_finished) state <= state + 1;
                end
            end
            4‘d08 : begin
                if(!Busy_Tx) begin
                    Data_Tx <= data_output[64-4*8-1:64-(4+1)*8];
                    Wrsig <= 1; 
                    state <= state + 1;
                    wait_cnt <= 12‘d0;
                    wait_finished <= 1‘b0;
                end
            end
            4‘d09 : begin
                if(Busy_Tx) begin
                    Wrsig <= 0;
                end
                else begin
                    wait_cnt <= wait_cnt + 1;
                    if(wait_cnt == 12‘hA00) begin
                        wait_cnt <= 12‘d0;
                        wait_finished <= 1‘b1;
                    end
                    else if(wait_cnt == 12‘d0 && wait_finished) state <= state + 1;
                end
            end
            4‘d10 : begin
                if(!Busy_Tx) begin
                    Data_Tx <= data_output[64-5*8-1:64-(5+1)*8];
                    Wrsig <= 1; 
                    state <= state + 1;
                    wait_cnt <= 12‘d0;
                    wait_finished <= 1‘b0;
                end
            end
            4‘d11 : begin
                if(Busy_Tx) begin
                    Wrsig <= 0;
                end
                else begin
                    wait_cnt <= wait_cnt + 1;
                    if(wait_cnt == 12‘hA00) begin
                        wait_cnt <= 12‘d0;
                        wait_finished <= 1‘b1;
                    end
                    else if(wait_cnt == 12‘d0 && wait_finished) state <= state + 1;
                end
            end
            4‘d12 : begin
                if(!Busy_Tx) begin
                    Data_Tx <= data_output[64-6*8-1:64-(6+1)*8];
                    Wrsig <= 1; 
                    state <= state + 1;
                    wait_cnt <= 12‘d0;
                    wait_finished <= 1‘b0;
                end
            end
            4‘d13 : begin
                if(Busy_Tx) begin
                    Wrsig <= 0;
                end
                else begin
                    wait_cnt <= wait_cnt + 1;
                    if(wait_cnt == 12‘hA00) begin
                        wait_cnt <= 12‘d0;
                        wait_finished <= 1‘b1;
                    end
                    else if(wait_cnt == 12‘d0 && wait_finished) state <= state + 1;
                end
            end
            4‘d14 : begin
                if(!Busy_Tx) begin
                    Data_Tx <= data_output[64-7*8-1:64-(7+1)*8];
                    Wrsig <= 1; 
                    state <= state + 1;
                    wait_cnt <= 12‘d0;
                    wait_finished <= 1‘b0;
                end
            end
            4‘d15 : begin
                if(Busy_Tx) begin
                    Wrsig <= 0;
                end
                else begin
                    wait_cnt <= wait_cnt + 1;
                    if(wait_cnt == 12‘hA00) begin
                        wait_cnt <= 12‘d0;
                        wait_finished <= 1‘b1;
                    end
                    else if(wait_cnt == 12‘d0 && wait_finished) begin//发送完成
                        finish <= 1;
                        busy <= 0;
                    end
                end
            end
            default:;
            endcase
        end
    end
endmodule

Uart_ClkDiv.v

/* Uart时钟信号 */
module Uart_ClkDiv(
	input Sys_CLK,  //50Mhz系统时钟
	output reg Uart_CLK //9600bps
	);
		
reg [7:0]Uart_CLK_Cnt;

initial
begin
	Uart_CLK <= 1‘b0;
	Uart_CLK_Cnt <= 8‘d0;
end

always@(posedge Sys_CLK)
begin
	if(Uart_CLK_Cnt <= 8‘d160)
		Uart_CLK_Cnt = Uart_CLK_Cnt + 1;
	else
	begin
		Uart_CLK = ~Uart_CLK;
		Uart_CLK_Cnt = 8‘d0;
	end
end

endmodule

Uart_Tx.v

/* Uart_Tx发送数据 */
module Uart_Tx(
    input Uart_CLK,
    input RST,
    input [7:0] Data_Tx,//8位待发送数据
    input Wrsig,
    output reg Idle,//空闲状态,0表示空闲,1表示忙碌
    output reg Signal_Tx//并转串,1位输出
    );
//16个时钟周期发送1bit数据

reg Send;
reg WrsigBuf;
reg WrsigRise;
reg Presult;
reg	[7:0]Tx_Cnt;

parameter paritymode = 1‘b0;

always@(posedge Uart_CLK)	//检测写入信号的上升沿
begin
   WrsigBuf <= Wrsig;
   WrsigRise <= (~WrsigBuf) & Wrsig;
end

always@(posedge Uart_CLK)
begin
	if(WrsigRise && (~Idle))  		//当发送命令有效且线路为空闲时,启动新的数据发送进程
		Send <= 1‘b1;				//正在发送
	else if(Tx_Cnt == 8‘d168)      	//除非一帧资料发送结束,否则Send信号保持高电平
		Send <= 1‘b0;				//正在空闲
end

always@(posedge Uart_CLK or negedge RST)
begin
    if(!RST)Signal_Tx<=1‘b1;
    else begin
        if(Send == 1‘b1)  
        begin
            case(Tx_Cnt)                 //产生起始位
                8‘d0: 
                begin
                    Signal_Tx <= 1‘b0;
                    Idle <= 1‘b1;
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                8‘d16: 
                begin
                    Signal_Tx <= Data_Tx[0];    //发送数据0位
                    Presult <= Data_Tx[0]^paritymode;
                    Idle <= 1‘b1;
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                8‘d32: 
                begin
                    Signal_Tx <= Data_Tx[1];    //发送数据1位
                    Presult <= Data_Tx[1]^Presult;
                    Idle <= 1‘b1;
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                8‘d48: 
                begin
                    Signal_Tx <= Data_Tx[2];    //发送数据2位
                    Presult <= Data_Tx[2]^Presult;
                    Idle <= 1‘b1;
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                8‘d64: 
                begin
                    Signal_Tx <= Data_Tx[3];    //发送数据3位
                    Presult <= Data_Tx[3]^Presult;
                    Idle <= 1‘b1;
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                8‘d80: 
                begin 
                    Signal_Tx <= Data_Tx[4];    //发送数据4位
                    Presult <= Data_Tx[4]^Presult;
                    Idle <= 1‘b1;
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                8‘d96: 
                begin
                    Signal_Tx <= Data_Tx[5];    //发送数据5位
                    Presult <= Data_Tx[5]^Presult;
                    Idle <= 1‘b1;
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                8‘d112: 
                begin
                    Signal_Tx <= Data_Tx[6];    //发送数据6位
                    Presult <= Data_Tx[6]^Presult;
                    Idle <= 1‘b1;
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                8‘d128: 
                begin 
                    Signal_Tx <= Data_Tx[7];    //发送数据7位
                    Presult <= Data_Tx[7]^Presult;
                    Idle <= 1‘b1;
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                8‘d144: 
                begin
                    Signal_Tx <= Presult;      //发送奇偶校验位
                    Presult <= Data_Tx[0]^paritymode;
                    Idle <= 1‘b1;
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                8‘d160: 
                begin
                    Signal_Tx <= 1‘b1;         //发送停止位             
                    Idle <= 1‘b1;
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                8‘d168: 
                begin
                    Signal_Tx <= 1‘b1;             
                    Idle <= 1‘b0;       //一帧资料发送结束
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
                end
                default: 
                    Tx_Cnt <= Tx_Cnt + 8‘d1;
            endcase
        end
        else
        begin
            Signal_Tx <= 1‘b1;
            Tx_Cnt <= 8‘d0;
            Idle <= 1‘b0;
        end
    end
end

endmodule

Uart_Rx.v

/* Uart_Rx 用于接收数据 */
module Uart_Rx(
	input Uart_CLK,//采样时钟
	input RST,//复位信号
	input Signal_Rx,//UART数据输入

	output reg [7:0] Data_Rx,//接收数据输出
	output reg Rdsig,//置1时表示上层模块已经可以读8位数据了
	output reg DataError_Flag,//数据出错指示
	output reg FrameError_Flag//帧出错指示
	);


	reg [7:0]cnt;

	reg RxBuf;
	reg RxFall;
	reg Recieve;

	reg Presult;
	reg Idle;
	parameter paritymode = 1‘b0;

	always@(posedge Uart_CLK)   //检测线路的下降沿
	begin
		RxBuf <= Signal_Rx;
		RxFall <= RxBuf & (~Signal_Rx);
	end

	////////////////////////////////////////////////////////////////
	//启动串口接收程序
	////////////////////////////////////////////////////////////////
	always@(posedge Uart_CLK)
	begin
		if (RxFall && (~Idle))	//检测到线路的下降沿并且原先线路为空闲,启动接收数据进程  
			Recieve <= 1‘b1;	//正在接收
		else if(cnt == 8‘d170)  //除非接收数据完成,否则接收状态保持
			Recieve <= 1‘b0;
	end

	////////////////////////////////////////////////////////////////
	//串口接收程序, 16个时钟接收一个bit
	////////////////////////////////////////////////////////////////
	always@(posedge Uart_CLK or negedge RST)
	begin
		if (!RST)
		begin
			Idle<=1‘b0;
			cnt<=8‘d0;
			Rdsig <= 1‘b0;	 
			FrameError_Flag <= 1‘b0; 
			DataError_Flag <= 1‘b0;	  
			Presult<=1‘b0;
			Data_Rx <= 8‘b0;
		end	  
		else if(Recieve == 1‘b1)
		begin
			case(cnt)
				8‘d0:begin
					Idle <= 1‘b1;
					cnt <= cnt + 8‘d1;
					Rdsig <= 1‘b0;
				end
				8‘d24:begin                 //接收第0位数据
					Idle <= 1‘b1;
					Data_Rx[0] <= Signal_Rx;
					Presult <= paritymode^Signal_Rx;
					cnt <= cnt + 8‘d1;
					Rdsig <= 1‘b0;
				end
				8‘d40:begin                 //接收第1位数据  
					Idle <= 1‘b1;
					Data_Rx[1] <= Signal_Rx;
					Presult <= Presult^Signal_Rx;
					cnt <= cnt + 8‘d1;
					Rdsig <= 1‘b0;
				end
				8‘d56:begin                 //接收第2位数据   
					Idle <= 1‘b1;
					Data_Rx[2] <= Signal_Rx;
					Presult <= Presult^Signal_Rx;
					cnt <= cnt + 8‘d1;
					Rdsig <= 1‘b0;
				end
				8‘d72:begin               //接收第3位数据   
					Idle <= 1‘b1;
					Data_Rx[3] <= Signal_Rx;
					Presult <= Presult^Signal_Rx;
					cnt <= cnt + 8‘d1;
					Rdsig <= 1‘b0;
				end
				8‘d88:begin               //接收第4位数据    
					Idle <= 1‘b1;
					Data_Rx[4] <= Signal_Rx;
					Presult <= Presult^Signal_Rx;
					cnt <= cnt + 8‘d1;
					Rdsig <= 1‘b0;
				end
				8‘d104:begin            //接收第5位数据    
					Idle <= 1‘b1;
					Data_Rx[5] <= Signal_Rx;
					Presult <= Presult^Signal_Rx;
					cnt <= cnt + 8‘d1;
					Rdsig <= 1‘b0;
				end
				8‘d120:begin            //接收第6位数据    
					Idle <= 1‘b1;
					Data_Rx[6] <= Signal_Rx;
					Presult <= Presult^Signal_Rx;
					cnt <= cnt + 8‘d1;
					Rdsig <= 1‘b0;
				end
				8‘d136:begin            //接收第7位数据   
					Idle <= 1‘b1;
					Data_Rx[7] <= Signal_Rx;
					Presult <= Presult^Signal_Rx;
					cnt <= cnt + 8‘d1;
					Rdsig <= 1‘b0;
				end
				8‘d152:begin            //接收奇偶校验位    
					Idle <= 1‘b1;
					if(Presult == Signal_Rx)
						DataError_Flag <= 1‘b0;
					else
						DataError_Flag <= 1‘b1;       //如果奇偶校验位不对,表示数据出错
					cnt <= cnt + 8‘d1;
					Rdsig <= 1‘b0;
				end
				8‘d168:begin
					Idle <= 1‘b1;
					if(1‘b1 == Signal_Rx)
						FrameError_Flag <= 1‘b0;
					else
						FrameError_Flag <= 1‘b1;      //如果没有接收到停止位,表示帧出错
					cnt <= cnt + 8‘d1;
					Rdsig <= 1‘b0;
				end
				8‘d169:begin
					Rdsig <= 1‘b1;
					cnt <= cnt + 8‘d1;
				end
				default:
					cnt <= cnt + 8‘d1;
			endcase
		end	
		else
		begin
			cnt <= 8‘d0;
			Idle <= 1‘b0;
			Rdsig <= 1‘b0;	 
		end
	end
endmodule

本类排行

今日推荐

热门手游