学习内容:
通过串口发送字符串。同时还了解了WIFI相关的发展以及协议。
疑惑的产生:
暂时未想到方法,让程序只对字符串内容发送一次。
相关代码:
参数定义
`define SYS_FRQ 50_000_000
`define BAUD_115200
`ifdef BAUD_9600
`define BAUD_MAX 9600
`elsif BAUD_19200
`define BAUD_MAX 19200
`elsif BAUD_38400
`define BAUD_MAX 38400
`elsif BAUD_57600
`define BAUD_MAX 57600
`elsif BAUD_115200
`define BAUD_MAX 115200
`else
`define BAUD_MAX 9600
`endif
串口发送模块tx
`include "param.v"
module uart_tx(
input clk,
input rst_n,
input tx_req,
input [7:0] tx_din,//输入的并行数据(真正需要发送的数据串)(数据不够这么多位,自动补零?)
output reg tx_dout,//输出的串行数据
output dout_vld, //发送完成的标志
output arr_dout_vld //字符串全部发送完毕标志
);//开始的标志是 tx_req为1,结束的标志是 数据发送完,tx_flag随即置0
reg [12:0] cnt_bps;//波特率计数寄存器
wire add_cnt_bps; //波特率计数开始标志
wire end_cnt_bps; //波特率计数结束
reg [3:0] cnt_bit;//比特计数寄存器
wire add_cnt_bit;//比特计数开始标志
wire end_cnt_bit;//比特计数结束
reg tx_flag;
reg [9:0] tx_data;//需要发送的数据 (实际发送的数据串,即:包括包头包尾)
//
//波特率计数器(发送1bit需要的时间)
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_bps <= 0;
end
else if(add_cnt_bps)begin
if (end_cnt_bps) begin
cnt_bps <= 0;
end
else begin
cnt_bps <= cnt_bps +1;
end
end
else begin
cnt_bps <= cnt_bps ;
end
end
assign add_cnt_bps = tx_flag;
assign end_cnt_bps = add_cnt_bps && cnt_bps == (`SYS_FRQ/`BAUD_MAX)-1'd1 ;
//计数已经发送了多少位数据(确定当前应该发送第几位了)
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_bit <= 0;
end
else if(add_cnt_bit)begin
if (end_cnt_bit) begin
cnt_bit <= 0;
end
else begin
cnt_bit <= cnt_bit + 1;
end
end
else begin
cnt_bit <= cnt_bit;
end
end
assign add_cnt_bit = end_cnt_bps;
assign end_cnt_bit = add_cnt_bit && cnt_bit == 4'd9;//达到条件后,结束发送
//发送开始,结束的判断
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
tx_flag <= 0;
end
else if (end_cnt_bit) begin
tx_flag <= 1'b0;
end
else if(tx_req)begin //收到发送请求,则 将发送位(即tx_flag)置1
tx_flag <= 1'b1;
end
else begin
tx_flag <= tx_flag;
end
end
/*
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
flag_r0 <= 0;
flag_r1 <= 0;
end
else begin
flag_r0 <= tx_flag;
flag_r1 <= flag_r0;
end
end
assign negedge_flag = flag_r1 && ~flag_r0;
//获取第n个字符
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_arr <= 0;
end
else if(cnt_arr <= arr_length)begin
if (negedge_flag) begin//tx_flag由1变成0
cnt_arr <= cnt_arr + 1;
end
else if (cnt_arr == arr_length) begin
arr_dout_vld <= 1'd1;// 数据真正发送完毕
end
else begin
cnt_arr <= cnt_arr;
arr_dout_vld <= 1'd0;
end
end
else begin
cnt_arr <= 0;
end
end
*/
//拼接(打包)需要发送的数据
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
tx_data <= 10'b0;
end
else if(tx_req)begin
tx_data <= {1'b1,tx_din,1'b0};//注意:传送的时候 tx_data[0]=0 而不是1。 这里最后一位是1,是因为 要让接收端的默认信号变回高电平,便于下次低电平到来的时候,下降沿的产生
end
else begin
tx_data <= tx_data;
end
end
//开始发送数据
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
tx_dout <= 1'b1;
end
//发送端为什么不考虑0.1衔接不理想的问题?
//,因为发送端是发送,而不是读取,读取要判断该电平表示1还是0,而发送端不用读取、所以不用考虑0.1电平理想的问题
else if(tx_flag && cnt_bps == 1)begin
tx_dout <= tx_data[cnt_bit];
end
else begin
tx_dout <= tx_dout;
end
end
assign dout_vld = ~tx_flag;
endmodule
字符串定义模块
module send_data(
input clk,
input rst_n,
input dout_vld,
output reg [7:0] rx_byte,
output reg next_cnt_flag,
output reg send_vld
);
reg [7:0] data[5:0] ;
reg[2:0] cnt;
wire add_cnt;
wire end_cnt;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 3'd0;
end
else if(add_cnt)begin
if (end_cnt) begin
cnt <= 3'd0;
next_cnt_flag <= 1;
end
else begin
cnt <= cnt + 1'd1;
end
end
else begin
cnt <= cnt;
end
end
assign add_cnt = dout_vld;
assign end_cnt = add_cnt && cnt ==5;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rx_byte <= 0;
data[0] <= "H";
data[1] <= "E";
data[2] <= "L";
data[3] <= "L";
data[4] <= "O";
data[5] <= "!";
end
else begin
rx_byte <= data[cnt];
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
send_vld <= 1;
end
else if(end_cnt)begin
send_vld <= 1'b0;
end
else begin
send_vld <= 1'b1;
end
end
endmodule
顶层文件
module uart_send(
input clk,
input rst_n,
output tx
);
wire [7:0] tx_byte;
wire dout_vld;
wire next_cnt_flag;
send_data u_send_data(
.clk(clk),
.rst_n(rst_n),
.dout_vld(dout_vld),
.next_cnt_flag(next_cnt_flag),
.rx_byte(tx_byte)
);
uart_tx u_uart_tx(
.clk(clk),
.rst_n(rst_n),
.tx_din(tx_byte),
.tx_req(next_cnt_flag),
.dout_vld(dout_vld),
.tx_dout(tx)
);
endmodule