

10、串口实验
实现功能:借助串口调试助手,上位机发送一个字符,下位机接收,并把该字符发送给上位机
PS:开始用模块写,写起来自己都糊涂了,就搁置几天不写了,后来仔细把串口的原理和逻辑搞清楚,然后就开始重新写了,不用模块,不用状态机,完全按照自己的逻辑来,上电测试,一次性通过!噢耶!
结论:原理最重要!
(开始使用EEPW的视频了)
http://v.eepw.com.cn/video/play/id/2093
module fpga_uart(clk,rst_n,uart_rx,uart_tx);
input clk;
input rst_n;
input uart_rx;
output uart_tx;
reg[12:0] cnt;
reg neg_rx_start; %检测接收起始位信号
reg cnt_start; %计数器启动信号
reg tx_data;
reg[10:0] data;
reg[3:0] num,n;
reg rx_end; %接收结束信号
reg tx_end; %发送结束信号
reg tx_start; %发送开始信号
reg clk_bps;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt = 0;
else if(cnt == 13'd5208)
cnt = 0;
else if(cnt_start)
cnt = cnt + 1'b1;
else
cnt = 0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
neg_rx_start = 0;
cnt_start = 0;
end
else if(cnt < 13'd8)
begin
if(!uart_rx)
begin
cnt_start = 1;
if(cnt == 13'd7)
neg_rx_start = 1;
end
else if(rx_end)
begin
if(tx_end)
cnt_start = 0;
else
cnt_start = 1;
end
else if(neg_rx_start)
cnt_start = 1;
else
begin
neg_rx_start = 0;
cnt_start = 0;
end
end
else if(num == 4'd11)
begin
neg_rx_start = 0;
cnt_start = 0;
end
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
clk_bps = 0;
else if(cnt == 13'd2604)
clk_bps = 1;
else
clk_bps = 0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
num = 0;
rx_end = 0;
data = 11'd0;
end
else if(num == 11)
begin
num = 0;
rx_end = 1;
end
else if(neg_rx_start)
begin
if(clk_bps)
begin
num = num + 1'b1;
case(num)
4'd1: data[0] = uart_rx;
4'd2: data[1] = uart_rx;
4'd3: data[2] = uart_rx;
4'd4: data[3] = uart_rx;
4'd5: data[4] = uart_rx;
4'd6: data[5] = uart_rx;
4'd7: data[6] = uart_rx;
4'd8: data[7] = uart_rx;
4'd9: data[8] = uart_rx;
4'd10: data[9] = uart_rx;
4'd11: data[10] = uart_rx;
endcase
end
end
else if(tx_end)
rx_end = 0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
tx_start = 0;
else if(tx_end)
tx_start = 0;
else if(rx_end)
tx_start = 1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
tx_end = 0;
n = 0;
end
else if(neg_rx_start)
tx_end = 0;
else if(n == 4'd10)
begin
tx_end = 1;
n = 0;
end
else if(tx_start)
begin
if(clk_bps)
begin
case(n)
4'd0: tx_data = 1'b0;
4'd1: tx_data = data[1];
4'd2: tx_data = data[2];
4'd3: tx_data = data[3];
4'd4: tx_data = data[4];
4'd5: tx_data = data[5];
4'd6: tx_data = data[6];
4'd7: tx_data = data[7];
4'd8: tx_data = data[8];
4'd9: tx_data = 1'b1;
default: tx_data = 1'b1;
endcase
n = n + 1;
end
end
end
assign uart_tx = tx_data;
endmodule
实现功能:借助串口调试助手,上位机发送一个字符,下位机接收,并把该字符发送给上位机
PS:开始用模块写,写起来自己都糊涂了,就搁置几天不写了,后来仔细把串口的原理和逻辑搞清楚,然后就开始重新写了,不用模块,不用状态机,完全按照自己的逻辑来,上电测试,一次性通过!噢耶!
结论:原理最重要!
(开始使用EEPW的视频了)
http://v.eepw.com.cn/video/play/id/2093
module fpga_uart(clk,rst_n,uart_rx,uart_tx);
input clk;
input rst_n;
input uart_rx;
output uart_tx;
reg[12:0] cnt;
reg neg_rx_start; %检测接收起始位信号
reg cnt_start; %计数器启动信号
reg tx_data;
reg[10:0] data;
reg[3:0] num,n;
reg rx_end; %接收结束信号
reg tx_end; %发送结束信号
reg tx_start; %发送开始信号
reg clk_bps;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt = 0;
else if(cnt == 13'd5208)
cnt = 0;
else if(cnt_start)
cnt = cnt + 1'b1;
else
cnt = 0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
neg_rx_start = 0;
cnt_start = 0;
end
else if(cnt < 13'd8)
begin
if(!uart_rx)
begin
cnt_start = 1;
if(cnt == 13'd7)
neg_rx_start = 1;
end
else if(rx_end)
begin
if(tx_end)
cnt_start = 0;
else
cnt_start = 1;
end
else if(neg_rx_start)
cnt_start = 1;
else
begin
neg_rx_start = 0;
cnt_start = 0;
end
end
else if(num == 4'd11)
begin
neg_rx_start = 0;
cnt_start = 0;
end
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
clk_bps = 0;
else if(cnt == 13'd2604)
clk_bps = 1;
else
clk_bps = 0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
num = 0;
rx_end = 0;
data = 11'd0;
end
else if(num == 11)
begin
num = 0;
rx_end = 1;
end
else if(neg_rx_start)
begin
if(clk_bps)
begin
num = num + 1'b1;
case(num)
4'd1: data[0] = uart_rx;
4'd2: data[1] = uart_rx;
4'd3: data[2] = uart_rx;
4'd4: data[3] = uart_rx;
4'd5: data[4] = uart_rx;
4'd6: data[5] = uart_rx;
4'd7: data[6] = uart_rx;
4'd8: data[7] = uart_rx;
4'd9: data[8] = uart_rx;
4'd10: data[9] = uart_rx;
4'd11: data[10] = uart_rx;
endcase
end
end
else if(tx_end)
rx_end = 0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
tx_start = 0;
else if(tx_end)
tx_start = 0;
else if(rx_end)
tx_start = 1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
tx_end = 0;
n = 0;
end
else if(neg_rx_start)
tx_end = 0;
else if(n == 4'd10)
begin
tx_end = 1;
n = 0;
end
else if(tx_start)
begin
if(clk_bps)
begin
case(n)
4'd0: tx_data = 1'b0;
4'd1: tx_data = data[1];
4'd2: tx_data = data[2];
4'd3: tx_data = data[3];
4'd4: tx_data = data[4];
4'd5: tx_data = data[5];
4'd6: tx_data = data[6];
4'd7: tx_data = data[7];
4'd8: tx_data = data[8];
4'd9: tx_data = 1'b1;
default: tx_data = 1'b1;
endcase
n = n + 1;
end
end
end
assign uart_tx = tx_data;
endmodule
回复
打赏帖 | |
---|---|
C语言函数宏的三种封装方式被打赏50分 | |
嵌入式LinuxC语言程序调试和宏使用技巧被打赏50分 | |
让代码中包含最新的编译时间信息被打赏50分 | |
【分享开发笔记,赚取电动螺丝刀】STM32F769LVGL优化显示被打赏26分 | |
rtthread硬件加密--2crc加密分析被打赏10分 | |
【分享开发笔记,赚取电动螺丝刀】STM32F769驱动ST7789以及显示优化被打赏36分 | |
【分享开发笔记,赚取电动螺丝刀】S32K146 PAL模拟I2C驱动适配被打赏23分 | |
我想要一部加热台+电源硬件设计规范被打赏16分 | |
我想要一部加热台+LED背光驱动芯片RT9293知识被打赏18分 | |
【分享开发笔记,赚取电动螺丝刀】S32K146 ADC 模块配置使用被打赏24分 |