fpga verilog rs232 发送模块实现

RS-232是一种串行通信协议,用于在计算机和其他外部设备之间进行数据传输。RS-232定义了电气特性、信号级别、机械特性和传输速率等规范,为串行通信提供了一种标准化的接口。

RS-232通常使用DB9连接器,用于传输和接收数据、控制信号以及地线连接。

但除了235脚其它基本都省略了,一个发送一个接收还有个地。

rs232是单端传输,还有485,422 差分传输,485半双工,422 全双工,原理差不多

下面是verilog代码。

tx.v

c 复制代码
module  tx (
    input wire clk,
    input wire rst_n,
    input wire tx_begin,
    input wire[7:0] tx_pdata,
    output reg txd,
    output reg busy
);

localparam OSC = 50_000_000;
localparam BAUD = 115200;
//localparam BAUD = 57600;
//localparam BAUD = 38400;
//localparam BAUD = 19200;

localparam NUM = OSC/BAUD - 1;

reg[16:0] clk_cnt;

reg [1:0] stage;
reg [2:0] curbit;
reg [7:0] tx_data;
reg done;


always @(posedge clk or negedge rst_n  ) begin
    if (!rst_n ) begin
        busy <= 1'b0;
    end else if (tx_begin === 1'b1 && busy === 1'b0  ) begin // busy ignore
        busy <= 1'b1;
        tx_data <= tx_pdata;
    end else if (done) 
      busy <= 1'b0;
end

reg tx_clk_en;

always @(busy) begin
    if(busy)
        tx_clk_en <= 1'b1;
    else
        tx_clk_en <= 1'b0;
end

reg tx_stage_pulse;
always @(posedge clk or negedge rst_n ) begin
    if (!rst_n)
      clk_cnt <= 0;
    else if( tx_clk_en === 1'b0 || clk_cnt === NUM)
        clk_cnt <= 0;
    else 
        clk_cnt <= clk_cnt + 1;
end

always @(posedge clk) begin
    if (clk_cnt === 1)
      	tx_stage_pulse <= 1'b1;
      else
        tx_stage_pulse <= 1'b0;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        txd <= 1'b1;
        done <= 1'b0;
        stage <= 2'd0;
    end else if (busy) begin
        if (tx_stage_pulse) begin
            if (stage === 2'd0) begin
                txd <= 1'b0;
                done <= 1'b0;
                stage <= 2'b1;
                curbit <= 3'd0;
            end else if (stage === 2'b1) begin
                txd <= tx_data[curbit];
                if (curbit === 3'd7)
                    stage <= 2'd2;
                else
                    curbit <= curbit + 1;
            end else if (stage === 2'd2) begin
                txd <= 1'b1;
                stage <= 2'd3;
              end else if (stage === 2'd3) begin
                txd <= 1'b1;
                done <= 1'b1;
                stage <= 2'd0;
              end
        end
    end else begin
        txd <= 1'b1;
        done <= 1'b0;
        stage <= 2'd0;
    end
end

endmodule

测试

uart_test.v

c 复制代码
module uart_test (
    input wire clk,
    input wire rst_n,
    output wire txd
);

reg tx_begin;
reg[7:0] tx_data = 0;

reg[31:0] cnt;
parameter maxcnt = 32'd1500 ;
wire busy;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        cnt <= 0;
    else if (cnt == maxcnt) begin
        cnt <= 0;
        if(!busy) 
        	tx_data <= (tx_data + 1) & 8'h7f ;
        tx_begin <= 1'b1;
    end else begin
        tx_begin <= 1'b0;
        cnt <= cnt+1;
    end
end

tx tx1(clk,rst_n,tx_begin,tx_data,txd,busy);

endmodule

testbench

test.v

c 复制代码
module test;

reg rst_n=1 ;

initial begin
    $dumpfile("test.vcd");
    $dumpvars(0, test);

    #10 rst_n = !rst_n;
    #30 rst_n = !rst_n;
    #100000 $finish;
end

reg clk = 0;
always #1 clk = !clk;

wire txd;
uart_test uart1(clk,rst_n,txd);

endmodule

两个问题,一帧数据传输完成前,再次接到发送指令,直接丢弃,因为中间即使停止, 对方也会以为这是数据直到完成这一帧 , 有可能会打乱时序 ,或用FIFO。引出一位busy忙标志位。

二停止位,有1位,1.5位,2位的,测试了下若用1位停止位的话,发送停止位完成后,半个停止位内再次发送会出现乱码应该是232芯片有一个要求大于1.5的,从FPGA出来后先转232一个芯片,232再转usb一个芯片,稳定起见,停止位两位。

相关推荐
dadaobusi8 小时前
verilog重音符号
fpga开发
s09071369 小时前
Xilinx FPGA ISERDES 使用详细介绍
fpga开发·xilinx·ddr·iserdes
虹科智能自动化11 小时前
虹科分享 | SocTek IP Cores:FPGA高端网络与时间同步解决方案
fpga开发·ip核·tsn时间敏感网络
秋风战士11 小时前
无线通信算法之340:信道均衡除法定标讨论
算法·fpga开发·信息与通信
FPGA小迷弟12 小时前
基于FPGA实现HDMI接口,选型/核心技术
学习·fpga开发·verilog·fpga·modelsim
szxinmai主板定制专家1 天前
基于 PC 的控制技术+ethercat+linux实时系统,助力追踪标签规模化生产,支持国产化
arm开发·人工智能·嵌入式硬件·yolo·fpga开发
博览鸿蒙1 天前
如何为春招的金三银四做好准备
fpga开发
FPGA小迷弟1 天前
FPGA处理图像需要用到的主流接口详解
学习·fpga开发·verilog·fpga·modelsim
LeoZY_2 天前
CH347 USB转JTAG功能使用笔记:CH347根据SVF文件实现任意FPGA下载
笔记·stm32·嵌入式硬件·fpga开发·硬件架构·硬件工程
博览鸿蒙2 天前
FPGA在高性能计算中的应用:数据流加速与优化
fpga开发