1.通过uart芯片实现数据回传测试,最终通过串口助手发生数据,第一部先将原理图P出。
2.代码仿真,对各个信号进行原理仿真,各个信号的名称意义。
(1).rx_data:就是上位机传来的数据信号。由于数据传输的时间与FPGA的时钟信号不一定同步,可能产生亚稳态,所以要将传来的信号进行握手延时。最终实现信号同步。rx_data_2与rx_data_3即为延时信号。(2)rx_en使能信号就是信号来的时候开始采集,其条件就是握手信号的不同,一个为0一个为1。(3)计数器是为了同步波特率9600和bit计数。(4).tmp_data为临时缓存数据的寄存器。(5).bit_flag是数据采集信号。
3.仿真信号,必须与原理信号一直,仿真文件需要随机产生
`timescale 1ns/1ns
module tx_tb;
reg sclk;
reg rst_n;
reg rx_in;
wire flag_o;
wire [7:0] data_o;
initial
begin
sclk=1'b0;
rst_n<=1'b0;
rx_in<=1'b0;
#200
rst_n<=1'b1;
end
always #10 sclk=~sclk;
reg [12:0] cnt;
reg [3:0] bit_cnt;
reg start;
parameter CNT=5207;
parameter BIT_CNT=9;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cnt<=13'd0;
else if(cnt==CNT)
cnt<=13'd0;
else cnt<=cnt+1'b1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
bit_cnt<=4'd0;
else if(bit_cnt==BIT_CNT&&cnt==CNT)
bit_cnt<=4'd0;
else if(cnt==CNT)
bit_cnt<=bit_cnt+1'b1;
always@(posedge sclk or negedge rst_n) //产生起始标志位
if(!rst_n)
start<=1'b1;
else if(cnt>=1&&cnt<=9)
start<=1'b0;
else start<=1'b1;
always@(posedge sclk or negedge rst_n) //产生随机数
if(!rst_n)
rx_in<=1'b0;
else case (bit_cnt)
4'd2: rx_in<={$random};
4'd3: rx_in<={$random};
4'd4: rx_in<={$random};
4'd5: rx_in<={$random};
4'd6: rx_in<={$random};
4'd7: rx_in<={$random};
4'd8: rx_in<={$random};
4'd9: rx_in<={$random};
default:rx_in<=1'b0; //只在规定范围内产生数据 其他状态清零
endcase
tx_crtl tx_crtl_inst(
.sclk (sclk),
.rst_n (rst_n),
.rx_in (rx_in),
.flag_o (flag_o),
.data_o (data_o)
);
endmodule
4.要时刻记住每个信号对比,而且延时握手信号处于在复位状态应该是高电位。
5.这次的测试文件写的有问题,修改后如下:
`timescale 1ns/1ns
module tx_tb;
reg sclk;
reg rst_n;
reg rx_in;
wire flag_o;
wire [7:0] data_o;
initial
begin
sclk=1'b0;
rst_n<=1'b0;
rx_in<=1'b0;
#200
rst_n<=1'b1;
end
always #10 sclk=~sclk;
reg [12:0] cnt;
reg [3:0] bit_cnt;
parameter CNT=5207;
parameter BIT_CNT=9;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cnt<=13'd0;
else if(cnt==CNT)
cnt<=13'd0;
else cnt<=cnt+1'b1;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
bit_cnt<=4'd0;
else if(bit_cnt==BIT_CNT&&cnt==CNT)
bit_cnt<=4'd0;
else if(cnt==CNT)
bit_cnt<=bit_cnt+1'b1;
always@(posedge sclk or negedge rst_n) //产生随机数
if(!rst_n)
rx_in<=1'b0; //复位状态应该为0 ,仿真产生数据有问题
else if(bit_cnt==0&&cnt==CNT) //起始位仿真
rx_in<=1'b0;
else if(bit_cnt>=1&&bit_cnt<=8&&cnt==CNT)//case (bit_cnt)
rx_in<={$random};
else if(bit_cnt==9&&cnt==CNT) //结束位仿真
rx_in<=1'b1;
uart_tx_train uart_tx_train_inst(
.sclk (sclk),
.rst_n (rst_n),
.rx_in (rx_in),
.data_o (data_o),
.flag_o (flag_o)
);
endmodule
6.最后为顶层文件设计,需要考虑明白FPGA的接受端和发送端如何与uart芯片进行连线。
7.uart芯片的发生端程序
module tx_crtl(
input wire sclk,
input wire rst_n,
input wire rx_in,
output reg flag_o,
output reg [7:0] data_o
);
reg [12:0] cnt;
reg [3:0] bit_cnt;
reg rx_in_1,rx_in_2;
reg rx_en; //使能信号值有问题
reg bit_flag;
reg [7:0]tmp_data;
reg tmp_flag;
parameter CNT=5207;
parameter BIT_CNT=9;
parameter bit_flag_cnt=2603; // 产生bit采集标志位
//parameter clean_flag=2610;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
rx_in_1<=1'b1;
else rx_in_1<=rx_in;
always@(posedge sclk or negedge rst_n) //输入信号延时
if(!rst_n)
rx_in_2<=1'b1;
else rx_in_2<=rx_in_1;
always@(posedge sclk or negedge rst_n) //产生计数使能信号
if(!rst_n)
rx_en<=1'b0;
else if(rx_in_1==1'b0&&rx_in_2==1'b1)
rx_en<=1'b1;
else if(bit_cnt==BIT_CNT&&cnt==CNT)
rx_en<=1'b0;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cnt<=13'd0;
else if(rx_en==1'b0)
cnt<=13'd0;
else if(cnt==CNT)
cnt<=13'd0;
else if(rx_en==1'b1)
cnt<=cnt+1'b1;
always@(posedge sclk or negedge rst_n) //位宽计数
if(!rst_n)
bit_cnt<=4'd0;
else if(rx_en==1'b0)
bit_cnt<=4'd0;
else if(bit_cnt==BIT_CNT&&cnt==CNT)
bit_cnt<=4'd0;
else if(cnt==CNT)
bit_cnt<=bit_cnt+1'b1;
always@(posedge sclk or negedge rst_n) //产生bit标志位
if(!rst_n)
bit_flag<=1'b0;
else if(cnt==bit_flag_cnt)
bit_flag<=1'b1;
else bit_flag<=1'b0;
always@(posedge sclk or negedge rst_n) //数据拼接
if(!rst_n)
tmp_data<=8'd0;
else if(bit_flag==1'b1&&bit_cnt>=4'd1&&bit_cnt<=4'd8)
tmp_data<={rx_in_2,tmp_data[7:1]}; //少写分号
//else if(bit_cnt==BIT_CNT&&cnt==clean_flag) 数据不清零条件
// tmp_data<=8'd0;
always@(posedge sclk or negedge rst_n) //数据拼接完成标志
if(!rst_n)
tmp_flag<=1'b0;
else if(bit_flag==1'b1&&bit_cnt==BIT_CNT)
tmp_flag<=1'b1;
else tmp_flag<=1'b0;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
data_o<=8'd0;
else if(tmp_flag==1'b1)
data_o<=tmp_data;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
flag_o<=1'b0;
else flag_o<=tmp_flag;
endmodule