小梅哥的FPGA教学视频跟学记录3
以下为自己我自己根据上一篇文章记录的串口发送模块进行模块调用发送数据,题目要求:
设计一个数据发送器,每10ms,以115200的波特率,发送一个数据,每次发送的数据都比前一个大1.
个人的调试记录:
调试过程发现:
Data初始值为1,第一个发送数据位1;但是发送后数据并未自加1,致使第二个发送数据仍为1,然后数据才进行自加1,得到Data=02.
对比以下两图,可以看到本该自加的Data因为少了一个bps_clk=1的信号,导致data不能加1;
为什么少了一个bps_clk呢,再回过头看发现Send_en少了一个周期!
经过调试发现,将
else if (counter > (434-1)*12)
Send_en <=0;
改为
else if (counter > 434*12-1)
Send_en <=0;
就可以得到下面非常漂亮且正确的仿真图!
放大看发送的第一个数据:00
发送的第五个数据:04
以下是完整的设计代码文件:
顶层模块:
module uart_tx_test (
Clk ,
Reset_n ,
uart_tx
);
input Clk ;
input Reset_n ;
output uart_tx ;
wire Tx_Done ;
wire bps_clk ;
wire [17:0] bps_cnt ;
reg [7:0] Data ;
reg Send_en ;
uart_byte_tx uart_byte_tx(
.Data (Data),
.Send_en (Send_en),
.Clk (Clk),
.Reset_n (Reset_n),
.Baud_set (3'd4),
.uart_tx (uart_tx),
.Tx_Done (Tx_Done),
.bps_clk (bps_clk),
.bps_cnt (bps_cnt)
);
reg [18:0] counter; //计数10ms
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0;
else if (counter == 500000-1)
counter <= 0;
else
counter <= counter +1'b1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Send_en <=0;
else if (counter > 434*12-1)
Send_en <=0;
else
Send_en <=1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Data <= 0;
else if((Tx_Done && bps_clk) )
Data <= Data +1'b1;
endmodule
被调用的发送字节模块:
module uart_byte_tx(
Data,
Send_en,
Clk,
Reset_n,
Baud_set,
uart_tx,
Tx_Done,
bps_clk,
bps_cnt
);
input [7:0] Data;
input Send_en; //发送数据的使能信号
input Clk;
input Reset_n;
input [2:0] Baud_set;
output reg uart_tx;
output reg Tx_Done; //标志数据发送完成
output wire bps_clk; //作为周期计数的触发信号
output reg [17:0] bps_cnt; //用于计数发送数据位数
//Baud_set = 0: 就让波特率=9600
//Baud_set = 1: 就让波特率=19200
//Baud_set = 2: 就让波特率=38400
//Baud_set = 3: 就让波特率=57600
//Baud_set = 4: 就让波特率=115200
reg [17:0]bps_DR; //18位是最低波特率300对应算出的计数器需要最多位
always@(*)
case(Baud_set)
0:bps_DR =1000000000/9600/20;
1:bps_DR =1000000000/19200/20;
2:bps_DR =1000000000/38400/20;
3:bps_DR =1000000000/57600/20;
4:bps_DR =1000000000/115200/20;
default:bps_DR =1000000000/9600/20;
endcase
reg [17:0] div_cnt;//计数器,一个周期
assign bps_clk = ( div_cnt==bps_DR-1);
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
div_cnt <= 0;
else if(Send_en) begin
if(bps_clk)
div_cnt <= 0;
else
div_cnt <= div_cnt + 1'b1;
end
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
bps_cnt <= 0;
else if(Send_en) begin
if (bps_clk)begin
if(bps_cnt == 11) //十位数据要保证十个周期,相当于十段线段,需要十一个点
bps_cnt <= 0;
else
bps_cnt <= bps_cnt + 1'b1;
end
end
else
bps_cnt <= 0;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n) begin
uart_tx <=1'b1;
Tx_Done <= 0;
end
else begin
case(bps_cnt)
1:begin uart_tx<=0;Tx_Done <=1'b0; end
2:uart_tx <= Data[0];
3:uart_tx <= Data[1];
4:uart_tx <= Data[2];
5:uart_tx <= Data[3];
6:uart_tx <= Data[4];
7:uart_tx <= Data[5];
8:uart_tx <= Data[6];
9:uart_tx <= Data[7];
10:uart_tx <= 1;
11:begin uart_tx <= 1;Tx_Done <= 1'b1; end
default:begin uart_tx<=1;Tx_Done <=1'b0; end
endcase
end
endmodule
tb文件代码:
`timescale 1ns / 1ns
module uart_tx_test_tb();
reg Clk;
reg Reset_n;
wire uart_tx;
uart_tx_test uart_tx_test(
.Clk (Clk ),
.Reset_n (Reset_n),
.uart_tx (uart_tx)
);
initial Clk =1;
always#10 Clk=~Clk;
initial begin
Reset_n=0;
#201;
Reset_n=1;
#50000000;
$stop;
end
endmodule