通过Python设计串口调试助手,结合FPGA串口工程进行验证

一、用python设计串口

import serial
while(1):
    try:
        #打开串口
        ser = serial.Serial("COM3",115200,timeout=0.5)
        print("打开串口",ser)

        #向串口写入数据
        data = input("输入发送的数据:")
        ser.write(data.encode('gbk'))
        #接受数据
        receive_data = ser.readline()
        receive = receive_data.decode('gbk')
        print("接收到的数据为:",receive)
        ser.close()#关闭串口
    except Exception as e:
        print("打开串口失败!\n",e)

二、打开Quartus,在FPGA上运行uart代码

1.顶层文件

module control(
    input               clk,
    input               rst_n,
    input      [7:0]    rx_din,   
    input               rx_vld,     //接受信号发送出去的有效标志 
    input               busy,

    output reg [7:0]    tx_din,
    output reg          tx_vld      //?为什么是reg
);
    parameter SEND_BYTE = 8 ; //FIFO中每存够8字节数据,就连续发送一次
//中间信号定义
    reg             rdreq_sig;   //?
    wire   [7:0]     data_sig;
    wire             wrreq_sig;
    wire             empty_sig;
    wire             full_sig;
    wire   [7:0]     q_sig;
    wire   [7:0]     usedw_sig;


    reg             rdreq_sig_flag;   //?

//rdreq_sig_flag  读请求标志
    always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                rdreq_sig_flag <= 1'b0;
            end 
            else if(usedw_sig >= SEND_BYTE)begin 
                rdreq_sig_flag <= 1'b1;
            end 
            else if(empty_sig) begin 
                rdreq_sig_flag <= 1'b0;
            end 
    end

//rdreq_sig  读信号   (随时可以读 ,只要有数据进来且满足对应条件    读请求标志拉高&& 非空 && busy为低电平)
    always @(*)begin 
            if(rdreq_sig_flag && empty_sig == 1'b0 && busy == 1'b0)begin
                rdreq_sig <= 1'b1;
            end 
            else begin
                rdreq_sig <= 1'b0;
            end
    end

//tx_din

    always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
               tx_din <= 1'b0;
            end 
            else begin 
               tx_din <= q_sig;
            end 
    end

//tx_vld
    always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                tx_vld <= 1'b0;
            end 
            else if(rdreq_sig)begin 
                tx_vld <= 1'b1;
            end 
            else begin 
                tx_vld <= 1'b0;
            end 
    end

    assign wrreq_sig = rx_vld && full_sig == 1'b0;  //接受到有效数据的发送请求 && fifo没满 
    assign data_sig = rx_din;


    fifo	fifo_inst (
	.aclr ( ~rst_n ),      //高电平有效
	.clock ( clk ),
	.data ( data_sig ),
	.rdreq ( rdreq_sig ),
	.wrreq ( wrreq_sig ),
	.empty ( empty_sig ),
	.full ( full_sig ),
	.q ( q_sig ),
	.usedw ( usedw_sig )
	);

endmodule


2.uart_rx接收模块

module uart_rx( 
   input                clk,
   input                rst_n,
   input  [2:0]         baud_set,
   input                din, //串行的输入数据

   output  reg [7:0]    rx_dout,   //8bit接收数据输出
   output  reg          rx_vld    //接收数据输出有效

);		

//参数定义 每个波特率下计数器最大计数值
localparam  BPS_115200 = 434,
            BPS_57600  = 868,
            BPS_38400  = 1302,
            BPS_19200  = 2604,
            BPS_9600   = 5208;
//中间信号    

reg   [12:0]      cnt_bps;
wire              add_cnt_bps;
wire              end_cnt_bps;

reg   [9:0]       cnt_bit;
wire              add_cnt_bit;
wire              end_cnt_bit;

reg  [12:0]       rx_bps;   //

reg  [9:0]       rx_data_r;   //接受一帧数据(起始位,数据位,停止位)

reg               din_r0; //同步
reg               din_r1; //打拍
reg               din_r2;

wire              nedge;

reg              rx_flag;


always @(*)begin
   case(baud_set)
      0:rx_bps = BPS_115200;
      1:rx_bps = BPS_57600;
      2:rx_bps = BPS_38400;
      3:rx_bps = BPS_19200;
      4:rx_bps = BPS_9600;
      default : rx_bps = BPS_115200;
   endcase
end


//cnt_bps 计数器
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
      cnt_bps <= 0;
   end 
   else if(add_cnt_bps)begin 
      if(end_cnt_bps)begin 
         cnt_bps <= 0;
      end
      else begin 
         cnt_bps <= cnt_bps + 1;
      end 
   end
end 
assign add_cnt_bps = rx_flag  ;
assign end_cnt_bps = add_cnt_bps && cnt_bps == rx_bps -1 ;

//同步   打拍
always @(posedge clk or negedge rst_n)begin
   if (!rst_n)begin
      din_r0 <= 1'b1;
      din_r1 <= 1'b1;
   end
   else begin
      din_r0 <= din;
      din_r1 <= din_r0;   //打拍
      din_r2 <= din_r1;

   end
end

//检测到下降沿
assign nedge = ~din_r1 & din_r2;

//rx_flag 
always @(posedge clk or negedge rst_n)begin 
      if(!rst_n)begin
          rx_flag <= 1'b0;
      end 
      else if(nedge && rx_flag == 1'b0 )begin 
         rx_flag <= 1'b1; 
      end 
      else if(end_cnt_bit && rx_flag == 1'b1)begin
         rx_flag <= 1'b0;
      end 
end


//cnt_bit 计数器
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
       cnt_bit <= 0;
   end 
   else if(add_cnt_bit)begin 
      if(end_cnt_bit)begin 
         cnt_bit <= 0;
      end
      else begin 
         cnt_bit <= cnt_bit + 1;
      end 
   end
end 
assign add_cnt_bit = end_cnt_bps;
assign end_cnt_bit = add_cnt_bit && (cnt_bit == 10-1 || rx_data_r[0]);

//rx_data_r 
always @(posedge clk or negedge rst_n)begin
    if(!rst_n) begin
      rx_data_r <= 0;
    end
    else if (rx_flag &&  cnt_bps == (cnt_bps>>1 ))begin
       rx_data_r[cnt_bit] <= din ;
    end
end

//rx_dout
always @(posedge clk or negedge rst_n) begin
   if(!rst_n) begin
      rx_dout <= 0;
   end
   else if (end_cnt_bit)begin
      rx_dout <= rx_data_r[8:1] ;
   end
end

//rx_vld
   always @(posedge clk or negedge rst_n) begin
      if(!rst_n)begin
         rx_vld <= 1'b0;
      end
      else if (end_cnt_bit)begin
         rx_vld <= 1'b1;
      end
      else  begin
         rx_vld <= 1'b0;
      end
   end
                        
endmodule

3.uart发送模块


module uart_tx(
    input         clk,
    input         rst_n,
    input  [2:0]  baud_set,
    input  [7:0]  tx_din,    //发送数据(8bit)
    input         tx_vld,    //发送数据有效指示标志(发送请求)

    output  reg   tx_dout ,
    output   reg   busy    
);

//参数定义 每个波特率下计数器最大计数值
    localparam  BPS_115200 = 434,
                BPS_57600  = 868,
                BPS_38400  = 1302,
                BPS_19200  = 2604,
                BPS_9600   = 5208;

//中间信号    
    reg   [12:0]  cnt_bps;    //波特率计数器
    wire          add_cnt_bps;
    wire          end_cnt_bps;

    reg   [3:0]   cnt_bit;    //bit计数器   0-9
    wire          add_cnt_bit;
    wire          end_cnt_bit;

    reg          tx_flag;

    reg    [12:0] tx_bps;

    reg    [9:0]  tx_data_r;  //表示一帧的数据(10bit)

//tx_bps用组合逻辑做一个波特率选择器
    always @ (*)begin
        case(baud_set)
            0 : tx_bps = BPS_115200;
            1 : tx_bps = BPS_57600;
            2 : tx_bps = BPS_38400;
            3 : tx_bps = BPS_19200;
            4 : tx_bps = BPS_9600;
            default : tx_bps = BPS_115200;
        endcase
    end 



//cnt_bps 计数器
    always @ (posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_bps <= 0;
        end
        else if (add_cnt_bps)begin
            if(end_cnt_bps)
                cnt_bps <= 0;
            else 
                cnt_bps <= cnt_bps + 1;    
        end

    end

    assign add_cnt_bps = tx_flag ;
    assign end_cnt_bps = add_cnt_bps && cnt_bps == tx_bps - 1;


//cnt_bit 计数器
    always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                cnt_bit <= 0;
            end 
            else if(add_cnt_bit)begin 
                if(end_cnt_bit)
                    cnt_bit <= 0;
                else   
                    cnt_bit <= cnt_bit + 1;  
            end 
    end
    assign add_cnt_bit = end_cnt_bps;
    assign end_cnt_bit = add_cnt_bit && cnt_bit == 10-1;


//tx_flag
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            tx_flag <= 1'b0;
        end
        else if(tx_vld)       //当有发送请求时,flag = 1; 
            tx_flag <= 1'b1;
        else if(end_cnt_bit)   //当10bit数据发送完的时候 tx_flag = 0;
            tx_flag <= 1'b0;
    end


//tx_dout
    //assign tx_data_r = tx_vld?{1'b1,tx_din,1'b0}:tx_data_r;
    always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
               tx_data_r <= 0;
            end 
            else if(tx_vld)begin 
                tx_data_r <= {1'b1,tx_din,1'b0};
            end 
    end

    always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                tx_dout <= 1'b1;  //初始状态为高电平   ?原因:如果是低电平的话 ,当下一次发送数据时,就会误以为是起始位
            end 
            else if(tx_flag && cnt_bps == 2-1 )begin  //发送信号拉高且bps计数器开始计数时
                tx_dout <= tx_data_r[cnt_bit];
            end 
            else begin 
                tx_dout <= tx_dout;
            end 
    end

    /*always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                busy <= 0;
            end 
            else if(tx_vld || tx_flag)begin 
                busy <= 1'b1;
            end 
            else begin 
                busy <= 0
            end 
    end*/
//busy
    always @(*)begin 
        if(tx_vld || tx_flag)begin 
            busy = 1'b1;
        end 
        else begin 
            busy = 0;
        end 
    end

endmodule

三、操作流程

(需要FPGA的开发板)先运行uart串口代码,在运行python串口代码

在这里插入图片描述

运行结果:

在这里插入图片描述

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值