手写一个uart协议——rs232(未完)

发布于:2024-05-01 ⋅ 阅读:(25) ⋅ 点赞:(0)

先了解一下关于uart和rs232的基础知识

本篇内容:

一、RS232的回环测试

上位机由串口助手通过 rx 线往 FPGA 发 8 比特数据,当 FPGA接收到 8 比特数据后,再通过 tx 线把接收到的 8 比特数据给上位机发回去,要求上位机接收到的数据和上位机发送的数据一样,并且保证连续发送也没问题。

在这里插入图片描述

1.1模块整体架构

在这里插入图片描述
在这里插入图片描述

1.2 rx模块设计

1.2.1 波形设计

在这里插入图片描述

1.2.2代码实现与tb

代码:

module uart_rx(
    input wire clk,
    input wire rst,
    input wire rx,
    output reg [7:0]po_data,
    output reg po_flag
    );

parameter CNT_END=100;  //9600bps cnt=5207  sim时,cnt=100;
parameter CNT_END_HALF=CNT_END/2;

reg rx_t;
reg rx_tt;
reg rx_tt_reg;
reg [12:0] cnt;
reg cnt_flag;
reg bit_flag;
reg [3:0]bit_cnt;
// rx_t
always @(posedge clk) begin 
    if(rst==1'b1) begin
        rx_t <= 'd1;
    end 
    else begin
         rx_t<=rx ;
    end
end

// rx_tt
always @(posedge clk) begin 
    if(rst==1'b1) begin
        rx_tt <= 'd1;
    end 
    else begin
         rx_tt<=rx_t ;
    end
end

// rx_tt_reg
always @(posedge clk) begin 
    if(rst==1'b1) begin
        rx_tt_reg <= 'd1;
    end 
    else begin
         rx_tt_reg<=rx_tt ;
    end
end

//cnt
always @(posedge clk) begin 
    if(rst==1'b1) begin
         cnt<= 'd0;
    end 
    else if (cnt_flag==1'b1 && cnt==CNT_END) begin
        cnt<='d0;
    end
    else if (cnt_flag==1'b1) begin
        cnt<=cnt+1'b1;
    end
    else if (bit_cnt=='d8 && bit_flag==1'b1) begin
        cnt<='d0;
    end
end

//bit_flag
always @(posedge clk) begin 
    if(rst==1'b1) begin
        bit_flag <= 'd0;
    end 
    else if (cnt_flag==1'b1 && cnt==CNT_END_HALF) begin
        bit_flag<='d1;
    end
    else 
        bit_flag<='d0;
end

// cnt_flag
always @(posedge clk) begin 
    if(rst==1'b1) begin
        cnt_flag <= 'd0;
    end 
    else if (rx_tt==1'b0 && rx_tt_reg==1'b1) begin
        cnt_flag<='d1;
    end
    else if (bit_cnt=='d8 && cnt==CNT_END_HALF) begin
        cnt_flag<='d0;
    end
end

// bit_cnt
always @(posedge clk) begin 
    if(rst==1'b1) begin
       bit_cnt  <= 'd0;
    end 
    else if (bit_cnt=='d8 && bit_flag==1'b1) begin
        bit_cnt<='d0;
    end
    else if (bit_flag==1'b1) begin
        bit_cnt<=bit_cnt+1'b1;
    end
  
end

// po_data
always @(posedge clk) begin 
    if(rst==1'b1) begin
        po_data <= 'd0;
    end 
    else if (bit_cnt>0 && bit_flag==1'b1) begin
        po_data<={rx,po_data[7:1]};
    end
end

// po_flag
always @(posedge clk) begin 
    if(rst==1'b1) begin
         po_flag<= 'd0;
    end 
    else if (bit_cnt=='d8 && bit_flag==1'b1) begin
        po_flag<='d1;
    end
    else 
        po_flag<='d0;
end
endmodule

tb:

`timescale 1ns / 1ps

module tb_rx();
	reg clk;
	reg rst;
	reg rx;
	wire [7:0] po_data;
	wire po_flag;

	initial begin
		clk=0;
		rst=1;
		#100
		rst=0;
	end

	initial begin
		rx=1;//空闲状态
		#100
		gen_rx();
		
	end


//这里模拟发送20帧数据,每次发送80~1的任意数,发送前rx拉低,表示起始位
//由于9600波特率需要计数5207次,为了仿真方便,假设只需要计数100次。
	task gen_rx;
		integer i;
		integer j;
		begin		
			for (j = 0; j < 20; j=j+1) begin
				rx=0;
				for ( i = 0; i < 8; i=i+1) begin  
					repeat(100) begin //每隔100周期发送1bit数据;
						@(posedge clk);  
					end
					rx={$random};
				end
				rx=1; //每发送完一帧数据后,rx恢复空闲状态,维持10个周期后继续发送数据,直到发够20帧数据。
			repeat(10) begin
				@(posedge clk);
			end		
			end
	    end
			
	endtask 

	always #5 clk=~clk;

		uart_rx inst_uart_rx (
			.clk     (clk),
			.rst     (rst),
			.rx      (rx),
			.po_data (po_data),
			.po_flag (po_flag)
		);

endmodule

1.2.4 仿真

在这里插入图片描述

1.3 tx模块设计

1.3.1波形设计

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到