FPGA学习笔记(十五)

uart串口接受模块的编写,宏定义参数由俩个分别是波特率和时钟频率,输入参数由时钟clk,复位rst,校验模式mod,校验模式有3种,当mod为0时是无校验模式,为1时是偶校验模式,为2时是奇校验模式。输入已读标志位read,为1时表示输入的有效信号已经被读取了。串口输入信号data_in。模块输出有两个,串口接受到的数据data_rx,与数据有效标志信号valid。

串口传输每一位所需要的时钟周期等于时钟频率除波特率,所以要定义一个计数器和一个标志位,当计数器计数到最大值时,标志位为高电平,最大值位上述所需要的时钟周期。

给串口输入的数据延迟3个时钟周期,赋值给一个3位的寄存器data,这一步目的时让输入的数据与时钟对其,并且消除亚稳态,此外这个寄存器还有个作用就是判断输入信号的下降沿是否来临,当data[2:1]等于2'b10时,就表示下降沿来临,有可能是接受到数据的起始位。

用状态机的方式表示接受数据的每一位,当接收到下降沿时,经过一个标志位,如果时上升沿,则表示此下降沿不是数据的起始位,因为前面说过每一位数据都会持续一个完整的标志位周期。若判断下降沿是数据的起始位时,后续8位就是发送的数据位了,让状态机给隔一个flag周期向下传递,知道第9位,状态机的第10种状态时,此时接受到时信号是数据的校验位,根据前面选择的检验方式进行校验,若检验成功进入11,校验失败进入12,之后11,12,都进入13。

根据状态机是否到过11为标志,当状态机到达11时,给数据有效位为1。当外部检测到数据有效位为1时读取传出的数据即可。读完后read置1,给数据有效位清零。数据传输的方式就是在状态机rt在2到9时进行传入数据寄存,把串行数据变为并行数据,当通过校验再把数据传输。

module uart_rx#(
parameter FREQ = 50_000_000,
parameter BAUDRATE = 115200
)(
input clk,
input rst,
input [1:0] mod,
input read,
input data_in,

output reg [7:0] data_rx,
output reg valid,
);

reg [31:0] cnt;
wire cnt_f= (cnt == FREQ/BAUDRATE/2 - 1);
reg f;

always@(posedge clk) if(rst) begin cnt<=0; f<=0;end else case(flag) 0: begin f<=0;cnt<=0;end
defautl: if(cnt_f) f=~f;cnt<=0;else cnt<=cnt+1;endcase

always@(posedge clk) data <= 0;else data <= {data[1:0],data_in};
wire flag = cnt_f & (~f);

reg [7:0] data_s;
reg [3;0] rt;
always@(clk) if(rst) rt <= 0;else case(rt)
0: if(data[2:1] == 2'b10) rt <= 1;
1: if(flag) rt <= (data[2]) ? 0 : 2;
2: if(flag) rt <= 3; 
3: if(flag) rt <= 4; 
4: if(flag) rt <= 5; 
5: if(flag) rt <= 6; 
6: if(flag) rt <= 7; 
7: if(flag) rt <= 8; 
8: if(flag) rt <= 9; 
9: if(flag) rt <= 10; 

10: if(flag)
begin
    case(mod)
    1: rt <= (data[2] != ^data_s) ? 11 : 12;
    2: rt <= (data[2] == ^data_s) ? 11 : 12;
    default: rt <= 11;
    endcase
end
11: if(flag) rt <= 13; 
12: if(flag) rt <= 13; 
13: if(flag) rt <= 0;
default: rt <= 0;
endcase
 
always@(posedge clk) if(rt == 2) data_s[0] <= data[2];
always@(posedge clk) if(rt == 3) data_s[1] <= data[2];
always@(posedge clk) if(rt == 4) data_s[2] <= data[2];
always@(posedge clk) if(rt == 5) data_s[3] <= data[2];
always@(posedge clk) if(rt == 6) data_s[4] <= data[2];
always@(posedge clk) if(rt == 7) data_s[5] <= data[2];
always@(posedge clk) if(rt == 8) data_s[6] <= data[2];
always@(posedge clk) if(rt == 9) data_s[7] <= data[2];

always@(posedge clk) if(rst) valid <= 0;else if(rt == 12) valid <= 1;else if(read) valid <= 0;

always@(posedge clk) if(rst) data_rx <= 0; else if(rt == 11)data_rx <= data_s;




endmodule

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值