FPGA 17 uart_Tx串口 数据流发送顶层设计(Top design)
模块名称: uart_tx_top
主要功能 :key_in 按键按下,发送一段字符串
实现(设计)流程: 在设计中,添加按键滤波模块,串口发送模块,并且在内部中设计控制信号,对按键按下的滤波以后的信号进行判断,进而完成对串口数据流的发送控制。
实验目的 : ① 了解FPGA的灵活性 ② 设计模块的的封装以及整体架构的设计的一个简单学习过程
uart_tx_top.v
module uart_tx_top(Clk,Rst_n,Rs232_Tx,key_in0,led);
input Clk;
input Rst_n;
input key_in0;
output Rs232_Tx;
output led;
reg send_en;
reg [7:0]data_byte;
wire key_flag0;
wire key_state0;
wire Tx_Done;
reg [2:0]cnt;
//数据按键,设计状态机或者线性序列机结构
localparam
byte1 = "H",
byte2 = "e",
byte3 = "l",
byte4 = "l",
byte5 = "o",
byte6 = 8'd0; // '\0'在quartus II 里面不支持
uart_byte_tx uart_byte_tx(
.Clk(Clk),
.Rst_n(Rst_n),
.data_byte(data_byte),
.send_en(send_en),
.baud_set(3'd0),
.Rs232_Tx(Rs232_Tx),
.Tx_Done(Tx_Done),
.uart_state(led)
);
key_filter key_filter0(
.Clk(Clk),
.Rst_n(Rst_n),
.key_in(key_in0),
.key_flag(key_flag0),
.key_state(key_state0)
);
//发送数据cnt计数个数
always@ (posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt <= 1'b0 ;
else if(Tx_Done)
cnt <= cnt + 1'b1;
else if (key_flag0 &! key_state0)
cnt <=1'b0;
//计数和按键结果控制使能发送信号send_en
always@ (posedge Clk or negedge Rst_n)
if(!Rst_n)
send_en <= 1'b0 ;
else if(key_flag0 & !key_state0)
send_en <=1'b1 ;
else if(Tx_Done & (cnt < 3'd5))
send_en <=1'b1 ;
else
send_en <=1'b0 ;
always@ (*)
case(cnt)
3'd0: data_byte <= byte1 ;
3'd1: data_byte <= byte2 ;
3'd2: data_byte <= byte3 ;
3'd3: data_byte <= byte4 ;
3'd4: data_byte <= byte5 ;
3'd5: data_byte <= byte6 ;
default : data_byte = 0 ;
endcase
endmodule
可以看到,我们在原来的基础上增加了几个小的功能模块:
1、带发送的线性数据(线性序列机器)
2、使用always 块 统计发送数据cnt计数个数
3、计数和按键结果控制使能发送信号send_en
个人总结: 这里的always块语句分别都是考虑各种信号对一个信号的控制。可以理解为多个影响因素对于单一变量的影响,而我们需要的是将这个影响使用always块把各个情况出现的结果写出来。另外,还需要考虑每一个影响的优先级顺序,优先级越高,顺序越前。
uart_tx_top_tb.tb 文件
`timescale 1ns/1ns
`define clk_period 20
module uart_tx_top_tb ;
reg Clk ;
reg Rst_n ;
reg press ;
wire key;
wire led ;
wire Rs232_Tx;
reg [7:0]data_byte;
reg [2:0]baud_set;
uart_tx_top uart_tx_top0(Clk,Rst_n,Rs232_Tx,key,led);
key_model key_model_0(press,key);
initial Clk = 1;
always#(`clk_period /2) Clk = ~Clk ;
initial begin
Rst_n =1'b0 ;
press = 1'b0 ;
#(`clk_period * 20 +1);
Rst_n =1'b1 ;
#(`clk_period * 20 +1);
press = 1'b1 ;
#(`clk_period * 20 +1);
press = 1'b0 ;
//使用wait 调用层次化方法 uart_tx_top0.Tx_Done
wait (uart_tx_top0.Tx_Done & (uart_tx_top0.cnt == 3'd5))
#(`clk_period * 20000 +1);
$stop ;
end
endmodule
同时发送一个数据流的方式:
仿真总结:
1、本次仿真一个是再次导入了 key_model输入仿真模块的使用
2、wait 语句的使用
3、层次话调用的方式。注:在层次化调用的时候,需要注意到模块名称和文件名称不能重合。