基于FPGA实现uart串口模块(Verilog)--------发送模块及整合
当接收模块接收到数据后,需要重新发送形成回环验证模块正确性。思路和结束模块有一点点的小差异。接收模块最终输出的是一个并行的八位数据,所以只有在最后输出保证输出结果正确就可以,而发送模块必须按照波特率时钟发送每一位的数据。具体代码实现如下
代码实现
module uart_tx(
//-----------input
clk,rst_n,pi_data,pi_flag,
//-----------output
tx_data
);
input clk;
input rst_n;
input [7:0] pi_data;
input pi_flag;
output tx_data;
parameter idle = 2'd0,
start = 2'd1,
work = 2'd2,
stop = 2'd3;
//------------------------------
localparam baud_cnt_end = 5207 ;
localparam baud_cnt_m = (baud_cnt_end + 1) / 2 - 1;
//------------------------------
//------------------------------
reg pi_flag1;
reg pi_flag2;
reg tx_flag;
reg [12:0] baud_cnt;
reg [3:0] bit_cnt;
reg tx_data;
reg [1:0] current_state;
reg [1:0] next_state;
always@(posedge clk )
begin
pi_flag1 <= pi_flag;
pi_flag2 <= pi_flag1;
end
//------------------------------
//第一个进程,同步时序always块,形式固定
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
current_state <= idle;
else
current_state <= next_state;
end
//第二个always,组合逻辑模块,描述状态迁移条件判断
always@(*)
begin
case(current_state)
idle:
begin
tx_flag = 1'b0;
begin
if(pi_flag2)
next_state = start;
else
next_state = idle;
end
end
start:
begin
tx_flag = 1'b1;
begin
if(bit_cnt == 4'd1)
next_state = work;
else
next_state = start;
end
end
work:
begin
tx_flag = 1'b1;
begin
if(bit_cnt == 4'd9)
next_state = stop;
else
next_state = work;
end
end
stop:
begin
tx_flag = 1'b1;
begin
if(bit_cnt == 4'd10)
next_state = idle;
else
next_state = stop;
end
end
default:
begin
next_state = idle;
end
endcase
end
//第三个进程,描述输出,同步时序always块
//reg [3:0] bit_cnt;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
bit_cnt <= 4'd0;
else
if(!tx_flag)
bit_cnt <= 4'd0;
else
if(baud_cnt == baud_cnt_end)
bit_cnt <= bit_cnt + 1'b1;
end
//reg [12:0] baud_cnt;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
baud_cnt <= 13'd0;
else
if(baud_cnt == baud_cnt_end)
baud_cnt <= 13'd0;
else
if(tx_flag)
baud_cnt <= baud_cnt + 1'b1;
else
baud_cnt <= 13'd0;
end
reg [7:0] pi_data_r;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
pi_data_r <= 8'd0;
else
if(pi_flag)
pi_data_r <= pi_data;
else
pi_data_r <= pi_data_r;
end
//define tx_data
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
tx_data <= 1'b1;
else
if(tx_flag)
case(bit_cnt)
4'd0 : tx_data <= 1'b0 ;
4'd1 : tx_data <= pi_data_r[0] ;
4'd2 : tx_data <= pi_data_r[1] ;
4'd3 : tx_data <= pi_data_r[2] ;
4'd4 : tx_data <= pi_data_r[3] ;
4'd5 : tx_data <= pi_data_r[4] ;
4'd6 : tx_data <= pi_data_r[5] ;
4'd7 : tx_data <= pi_data_r[6] ;
4'd8 : tx_data <= pi_data_r[7] ;
4'd9 : tx_data <= 1'b1 ;
default:;
endcase
else
tx_data <= 1'b1;
end
endmodule
顶层文件(模块整合)
module top_uart(
input clk ,
input rst_n ,
input rx_data ,
output tx_data
);
wire [7:0] data;
wire flag;
uart_tx A(
.clk (clk ),
.rst_n (rst_n ),
.pi_data (data ),
.pi_flag (flag ),
.tx_data (tx_data)
);
uart_rx B(
.clk (clk ),
.rst_n (rst_n ),
.rx_data (rx_data),
.po_data (data ),
.po_flag (flag )
);
endmodule
仿真代码
module tb_fsm;
// Inputs
reg clk;
reg rst_n;
reg rx_data;
// Outputs
wire tx_data;
// Instantiate the Unit Under Test (UUT)
top_uart uut (
.clk(clk),
.rst_n(rst_n),
.rx_data(rx_data),
.tx_data(tx_data)
);
always #10 clk = ~clk;
initial begin
// Initialize Inputs
clk = 0;
rst_n = 0;
rx_data = 1;
// Wait 100 ns for global reset to finish
#100;
rst_n = 1;
#104140;
rx_data = 1;
#104140;
rx_data = 1;
#104140;
rx_data = 1;
#104140;
rx_data = 1;
#104140;
rx_data = 1;
#104140;
rx_data = 0;//start
#104140;
rx_data = 0;//1
#104140;
rx_data = 1;//2
#104140;
rx_data = 0;//3
#104140;
rx_data = 1;//4
#104140;
rx_data = 0;//5
#104140;
rx_data = 1;//6
#104140;
rx_data = 0;//7
#104140;
rx_data = 1;//8
#104140;
rx_data = 1;
#104140;
rx_data = 1;
#104140;
rx_data = 1;
#104140;
rx_data = 1;
#104140;
rx_data = 1;
#104140;
rx_data = 0;
#104140;
rx_data = 1;//1
#104140;
rx_data = 0;
#104140;
rx_data = 1;
#104140;
rx_data = 0;//4
#104140;
rx_data = 1;
#104140;
rx_data = 0;
#104140;
rx_data = 1;
#104140;
rx_data = 0;//8
#104140;
rx_data = 1;
#104140;
rx_data = 1;
#104140;
rx_data = 1;
// Add stimulus here
end
endmodule
反思小结
对于uart,发送和接收应该是人机交互的一个方式,通过发送的字符控制内部等等其他东西。对于模块不理解的可以回头看看仿真图,对图中的各个时序进行理解。