先了解一下关于uart和rs232的基础知识
文章目录
- 一、RS232的回环测试
- 1.1模块整体架构
- 1.2 rx模块设计
- 1.2.1 波形设计
- 1.2.2代码实现与tb
- 1.2.4 仿真
- 1.3 tx模块设计
- 1.3.1波形设计
本篇内容:
一、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帧数据,每次发送8个0~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