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
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图四被打赏50分 | |
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 |