RS-232 Transmitter

    xiaoxiao2025-01-29  17

    目录

    串行化数据

    Verilog描述并仿真


    上篇博文讲到了如何产生波特率?(RS232 波特率时钟产生方法?)

    下面的内容是构建一个异步发送器:

    我们正在构建一个具有固定参数的“异步发送器”:8个数据位,2个停止位,无奇偶校验。

    它的工作方式如下:

    发送器在FPGA内部获取一个8位数据并将其串行化(从“TxD_start”信号置位时开始)。 在发生传输时断言“忙”信号(在此期间忽略“TxD_start”信号)。

    串行化数据


    要查看起始位,8个数据位和停止位,状态机似乎是合适的。

    reg [3:0] state; // the state machine starts when "TxD_start" is asserted, but advances when "BaudTick" is asserted (115200 times a second)always @(posedge clk)case(state)   4'b0000: if(TxD_start) state <= 4'b0100;   4'b0100: if(BaudTick) state <= 4'b1000; // start   4'b1000: if(BaudTick) state <= 4'b1001; // bit 0   4'b1001: if(BaudTick) state <= 4'b1010; // bit 1   4'b1010: if(BaudTick) state <= 4'b1011; // bit 2   4'b1011: if(BaudTick) state <= 4'b1100; // bit 3   4'b1100: if(BaudTick) state <= 4'b1101; // bit 4   4'b1101: if(BaudTick) state <= 4'b1110; // bit 5   4'b1110: if(BaudTick) state <= 4'b1111; // bit 6   4'b1111: if(BaudTick) state <= 4'b0001; // bit 7   4'b0001: if(BaudTick) state <= 4'b0010; // stop1   4'b0010: if(BaudTick) state <= 4'b0000; // stop2   default: if(BaudTick) state <= 4'b0000;endcase

    现在,我们只需要生成“TxD”输出。

    reg muxbit;always @(state[2:0])case(state[2:0])   0: muxbit <= TxD_data[0];   1: muxbit <= TxD_data[1];   2: muxbit <= TxD_data[2];   3: muxbit <= TxD_data[3];   4: muxbit <= TxD_data[4];   5: muxbit <= TxD_data[5];   6: muxbit <= TxD_data[6];   7: muxbit <= TxD_data[7];endcase // combine start, data, and stop bits togetherassign TxD = (state<4) | (state[3] & muxbit);


    Verilog描述并仿真

    Verilog描述:

    由于参考链接(https://www.fpga4fun.com/SerialInterface3.html)上的完整代码过于复杂,我自己改成简单的形式,并仿真:

    module ays_transmitter( input clk, input TxD_start, input [7:0] TxD_data, output TxD, output TxD_busy ); reg [3:0] TxD_state = 0; wire TxD_ready = (TxD_state==0); assign TxD_busy = ~TxD_ready; //Generate Baud Clock wire BitTick; BaudGen u_BaudGen( .clk(clk), .enable(TxD_busy), //generate baud clk only when transmiter data .BaudTick(BitTick) ); reg [7:0] TxD_shift = 0; always @(posedge clk) begin if(TxD_ready & TxD_start) TxD_shift <= TxD_data; else if(TxD_state[3] & BitTick) TxD_shift <= (TxD_shift >> 1); case(TxD_state) 4'b0000: if(TxD_start) TxD_state <= 4'b0100; 4'b0100: if(BitTick) TxD_state <= 4'b1000; // start bit 4'b1000: if(BitTick) TxD_state <= 4'b1001; // bit 0 4'b1001: if(BitTick) TxD_state <= 4'b1010; // bit 1 4'b1010: if(BitTick) TxD_state <= 4'b1011; // bit 2 4'b1011: if(BitTick) TxD_state <= 4'b1100; // bit 3 4'b1100: if(BitTick) TxD_state <= 4'b1101; // bit 4 4'b1101: if(BitTick) TxD_state <= 4'b1110; // bit 5 4'b1110: if(BitTick) TxD_state <= 4'b1111; // bit 6 4'b1111: if(BitTick) TxD_state <= 4'b0010; // bit 7 4'b0010: if(BitTick) TxD_state <= 4'b0011; // stop1 4'b0011: if(BitTick) TxD_state <= 4'b0000; // stop2 default: if(BitTick) TxD_state <= 4'b0000; endcase end assign TxD = (TxD_state<4) | (TxD_state[3] & TxD_shift[0]); // put together the start, data and stop bits endmodule

    BaudGen模块:

    module BaudGen( input clk, input enable, output BaudTick ); parameter ClkFrequency = 25000000; // 25MHz parameter Baud = 115200; parameter Ratio = ClkFrequency/Baud; parameter BaudGeneratorAccWidth = 16; parameter BaudGeneratorInc = (1<<BaudGeneratorAccWidth)/Ratio; reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc = 0; always @(posedge clk) if(enable) BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc; else BaudGeneratorAcc <= BaudGeneratorInc; assign BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth]; endmodule

    测试模块:

    `timescale 1ns / 1ps // // Create Date: 2019/05/26 16:06:48 // Design Name: // Module Name: ays_transmitter_tb // module ays_transmitter_tb( ); reg clk; reg TxD_start; reg [7:0] TxD_data; wire TxD; wire TxD_busy; initial begin clk = 0; forever #20 clk = ~clk; end initial begin TxD_start = 0; TxD_data = 8'b10010101; #50 TxD_start = 1; end ays_transmitter u_ays_transmitter( .clk(clk), .TxD_start(TxD_start), .TxD_data(TxD_data), .TxD(TxD), .TxD_busy(TxD_busy) ); endmodule

    仿真波形图:

    从上图可以看出,每一个波特时钟发送一bit数据:从低到高位发送10101001,之后发送两个结束位1.

    下面这幅图是显示下一次发送前的空闲期,TxD_busy为低。之后又进入了下一帧数据的发送。

     

     

    参考链接:

    https://www.fpga4fun.com/SerialInterface3.html

     

    最新回复(0)