概述
- 简述
- 核心代码
- 仿真测试
简述
串口发送是以一定速率发送单bit数据,通常一组数据为10bit。空闲状态为高电平,起始位为0,中间以低位在前的方式发送8bit数据,终止位为1。
采用计数器 [cnt_baud] 对系统时钟进行计数,计满值即为预设的波特率值 [baud_num]
在这个计数过程中,每当计数值为1时,就产生一个标志值 [flag1]
采用计数器 [cnt_for_flag1] 对flag1进行计数11次,当计数值达到11时,同步清零。
所以cnt_for_flag1 = 11 只能维持1个系统时钟,并不能维持一个baud_num。
能维持一个baud_num的为计数值1~10。利用cnt_for_flag1作为多路器的选择端分别发送出10个bit的数据。
当cnt_for_flag1值为11时,代表一次发送完成,产生done信号。
核心代码
module ser_tx(data,en,clk,rst,tx,done);
input [7:0] data;
input en;
input clk;
input rst;
output reg tx;
output reg done;
reg [15:0] baud_num = 16'd5207; //5207=9600、2603=19200、1301=38400、867=57600、433=115200
/*将引脚 <input [7:0] data> 进行一级寄存 -> reg_data*/
reg [7:0]reg_data;
always@(posedge clk or negedge rst) begin
if(!rst)
reg_data <= 8'b0;
else if(en)begin
reg_data <= data;
end
else
reg_data <= data;
end
/*计数器:0~5207~0~5207....*/
reg [15:0]cnt_baud;
always@(posedge clk or negedge rst)
begin
if(!rst)
cnt_baud <= 1'b0;
else if(cnt_baud == baud_num)
cnt_baud <= 1'b0;
else
cnt_baud <= cnt_baud + 1'b1;
end
/*0~5207这个过程中,每当计数到1的时候就产生一个flag*/
reg flag1;
always@(posedge clk or negedge rst)
begin
if(!rst)
flag1 <= 1'b0;
else if(cnt_baud == 16'd1)
flag1 <= 1'b1;
else
flag1 <= 1'b0;
end
/*对flag1进行计数,计数11次,但11只能维持1个clk,并不能维持9600bps,然后就被清0*/
reg [3:0] cnt_for_flag1;
always@(posedge clk or negedge rst)
begin
if(!rst)
cnt_for_flag1 <= 1'b0;
else if(cnt_for_flag1 == 4'd11)
cnt_for_flag1 <= 1'b0;
else if(flag1 == 1'd1)
cnt_for_flag1 <= cnt_for_flag1 + 1'b1;
else
cnt_for_flag1 <= cnt_for_flag1;
end
/*依次发送起始位、数据位、终止位*/
always@(posedge clk or negedge rst)
begin
if(!rst)
tx <= 1'd1; //根据时序图,tx的闲时状态是高电平。
else
begin
case (cnt_for_flag1)
4'd0: tx <= 1'd1; //空闲状态
4'd1: tx <= 1'd0; //起始位
4'd2: tx <= reg_data[0]; //低位在前
4'd3: tx <= reg_data[1];
4'd4: tx <= reg_data[2];
4'd5: tx <= reg_data[3];
4'd6: tx <= reg_data[4];
4'd7: tx <= reg_data[5];
4'd8: tx <= reg_data[6];
4'd9: tx <= reg_data[7];
4'd10: tx <= 1'd1; //终止位
default:tx <= 1'd1;//空闲状态
endcase
end
end
//每次计数器“cnt_for_flag1”值为11时,代表一次发送完成,产生done信号。
always@(posedge clk or negedge rst) begin
if(!rst)
done <= 1'd0;
else if(cnt_for_flag1 == 4'd11) //cnt_to_10计数到11自动清零
done <= 1'd1;
else
done <= 1'd0;
end
endmodule
仿真测试
发送8bit的 data1 = 8’b01001101 作为测试!
`timescale 1ns/1ns
module ser_tx_tb;
reg [7:0] data1;
reg en1;
reg clk1;
reg rst1;
wire tx1;
wire done1;
ser_tx txer
(
.data(data1),
.en(en1),
.clk(clk1),
.rst(rst1),
.tx(tx1),
.done(done1)
);
initial clk1 = 1'b1;
always#10 clk1 = ~clk1;
initial begin
rst1 = 1'b0; //未运行状态
#400;
rst1 = 1'b1;
data1 = 8'b01001101;
en1 = 1;
#20;//一个时钟周期
en1 = 0;
#4000000;
$stop;
end
endmodule
最后
以上就是结实奇迹为你收集整理的【verilog】UART串口发送(FPGA)简述核心代码仿真测试的全部内容,希望文章能够帮你解决【verilog】UART串口发送(FPGA)简述核心代码仿真测试所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复