代码规范:Verilog 代码规范_verilog代码编写规范-CSDN博客
开发流程:FPGA基础知识----第二章 FPGA 开发流程_fpga 一个项目的整个流程-CSDN博客
源码下载:GitHub - Redamancy785/FPGA-Learning-Record: 项目博客:https://blog.csdn.net/weixin_51460407
一、功能定义
二、设计输入
module uart_byte_tx(
data_i,
clk_i,
reset_i,
uart_tx_o,
led_o
);
input clk_i,reset_i;
input [7:0] data_i;
output uart_tx_o,led_o;
parameter BAUD_RATE = 9600; // 9600
parameter SENT_BIT_NUMBER = 10; // 1 + 8 + 1
parameter ONE_MS = 50_000;
parameter FREQUENCY = 1000 * ONE_MS;
parameter SEND_INTERVAL = 1_000; // ms
// BAUD_RATE_CNT = (1/BAUD_RATE)/(1/FREQUENCY) - 1
parameter BAUD_RATE_CNT = 5208;
// 波特率计数器
reg [12:0] baud_rate_cnt;
reg en_baud_rate_cnt;
always@(posedge clk_i or negedge reset_i)
if(!reset_i)
baud_rate_cnt <= 0;
else if(en_baud_rate_cnt)
if(baud_rate_cnt == (5208 - 1))
baud_rate_cnt <= 0;
else
baud_rate_cnt <= baud_rate_cnt + 1;
else
baud_rate_cnt <= 0;
// 发送位计数器
reg [3:0] bit_cnt;
always@(posedge clk_i or negedge reset_i)
if(!reset_i)
bit_cnt <= 0;
else if(baud_rate_cnt == (5208 - 1))
if(bit_cnt == SENT_BIT_NUMBER - 1)
bit_cnt <= 0;
else
bit_cnt <= bit_cnt + 1;
// 发送间隔计数器
reg [25:0] interval_cnt;
always@(posedge clk_i or negedge reset_i)
if(!reset_i)
interval_cnt <= 0;
else if(interval_cnt == SEND_INTERVAL * ONE_MS - 1)
interval_cnt <= 0;
else
interval_cnt <= interval_cnt + 1;
// 存储发送数据
reg [7:0] data;
always@(posedge clk_i)
if(interval_cnt == SEND_INTERVAL * ONE_MS - 1)
data <= data_i;
// 位发送逻辑
reg uart_tx_o;
always@(posedge clk_i or negedge reset_i)
if(!reset_i)
uart_tx_o <= 1;
else if(en_baud_rate_cnt) begin
case(bit_cnt)
0 : uart_tx_o <= 0;
1 : uart_tx_o <= data[0];
2 : uart_tx_o <= data[1];
3 : uart_tx_o <= data[2];
4 : uart_tx_o <= data[3];
5 : uart_tx_o <= data[4];
6 : uart_tx_o <= data[5];
7 : uart_tx_o <= data[6];
8 : uart_tx_o <= data[7];
9 : uart_tx_o <= 1;
default : uart_tx_o <= 1;
endcase
end
// LED翻转逻辑
reg led_o;
always@(posedge clk_i or negedge reset_i)
if(!reset_i)
led_o <= 0;
else if((bit_cnt == 9) && (baud_rate_cnt == (5208 - 1)))
led_o <= ~led_o;
// en_baud_rate_cnt 翻转逻辑
always@(posedge clk_i or negedge reset_i)
if(!reset_i)
en_baud_rate_cnt <= 0;
else if((bit_cnt == 9) && (baud_rate_cnt == (5208 - 1)))
en_baud_rate_cnt <= 0;
else if(interval_cnt == (SEND_INTERVAL * ONE_MS - 1))
en_baud_rate_cnt <= 1;
endmodule
三、功能仿真
`timescale 1ns / 1ns
module uart_byte_tx_tb();
reg u_clk_i,u_reset_i;
reg [7:0] u_data_i;
wire u_uart_tx_o,u_led_o;
uart_byte_tx U_uart_byte_tx_0(
.data_i(u_data_i),
.clk_i(u_clk_i),
.reset_i(u_reset_i),
.uart_tx_o(u_uart_tx_o),
.led_o(u_led_o)
);
defparam U_uart_byte_tx_0.SEND_INTERVAL = 10;
initial u_clk_i = 1;
always #10 u_clk_i = ~u_clk_i;
initial begin
u_reset_i = 0;
u_data_i = 8'b01011010;
#201;
u_reset_i = 1;
#40_000_000; // x_000_000 - xms
$stop;
end
endmodule