#今天也是咸鱼的一天~
UART是一个很基础的串口通信协议,有人打趣说只要有单片机的地方,就一定有uart。这话不假,不仅很多模块和单片机的通信有uart,单片机和上位机之间的通信,uart也是最常用的。(寒假的时候,就用C#写了一个上位机,用的就是串口)
Uart 的原理可以参考这个博客:FPGA的串口通讯(UART)
这几天用Robei EDA 给我的一个感想就是,在FPGA的使用设计上,如果是从原有的程序上移植,比较需要注意的就是一份代码,需要由多少个运算模块组成,每个模块的IO分配,变量类型和数据位的设置,还有对于testbech的设置。
而如果是独立的Verilog设计,设计方式是自上而下还是自下而上,每个模块的IO分配,一个模块内部变量的使用,parameter的设置。尤其是parameter,不适合每个模块都对parameter设置为常数,比较好的应该是把局部模块的parameter设置为一个“变量”,然后在顶层模块把这个“变量”设置为parameter。
回到正题……
uart 在robei EDA的库里是有封装好模块,可以直接调用。唯一的坏处就是,这个模块已经封装好了,不能进行任何修改。(当然,也没什么好修改的)
代码可以在Code里面看到。
如果不用这个模块,自己写一个,其实还挺麻烦的……
要分别写一个发送uart_tx
模块和接收uart_rx
模块,激励文件的编写也很麻烦……
分别是发送和接收的模块。代码我是参考正点原子的uart收发测试,上位机像FPGA发送一串数据,FPGA再把数据返回给上位机。
UART_TX
- 延时
//对发送使能信号uart_en延迟两个时钟周期
always@(posedge clk or negedge rst)
begin
if(!rst)
begin
uart_en_d0 <= 1'b0;
uart_en_d1 <= 1'b0;
end
else
begin
uart_en_d0 <= uart_en;
uart_en_d1 <= uart_en_d0;
end
end
- 取上升沿
assign flag = ~d0 & d1;
//捕获uart_en上升沿,得到一个时钟周期的脉冲信号
- 数据寄存
parameter BPS_CNT= CLK_FRE/UART_BPS;
//当脉冲信号en_flag到达时,寄存待发送的数据,并进入发送过程
always@(posedge clk or negedge rst)
begin
if(!rst)
begin
tx_flag <= 1'b0;
tx_data <= 8'b0;
end
else if(flag )
begin
tx_flag <= 1'b1;
tx_data <= uart_din;
end
else if((tx_cnt == 4'd9)&&(clk_cnt