FPGA基础——串行数据接收(Fsm serialdp)
我们想在串行接收机中加入奇偶校验。奇偶校验检查在每个数据字节后添加一个额外的位。我们将使用奇奇偶校验,其中接收到的9位中的1必须是奇数。例如,101001011个满足奇偶校验(有5个1) ,但001001011个不满足。
只有在正确接收到一个字节并且它的奇偶校验通过时,才断言完成信号。与串行接收机一样,该有限状态机需要确定开始位,等待所有9位(数据和奇偶校验) ,然后验证停止位是正确的。如果停止位没有在预期的时候出现,FSM 必须等到找到停止位之后才能尝试接收下一个字节。
注意,串行协议先发送低有效位,奇偶校验位在8个数据位之后,然后是高有效停止位。
1 module parity (
2 input clk,
3 input reset,
4 input in,
5 output reg odd);
6
7 always @(posedge clk)
8 if (reset) odd <= 0;
9 else if (in) odd <= ~odd;
10
11 endmodule
1 module top_module(
2 input clk,
3 input in,
4 input reset, // Synchronous reset
5 output [7:0] out_byte,
6 output done
7 ); //
8 parameter IDLE = 4'd0, START = 4'd1, RXD = 4'd2,STOP = 4'd3,WAIT = 4'd4,PARITY = 4'd5;
9 reg [7:0] out_byte_reg;
10 reg [3:0] current_state;
11 reg [3:0] next_state;
12 wire odd;
13 wire re;
14 reg [3:0]cnt_byte;
15
16 always@(posedge clk)begin
17 if(reset)begin
18 current_state <= IDLE;
19 end
20 else begin
21 current_state <= next_state;
22 end
23 end
24
25 always@(*)begin
26 case(current_state)
27 IDLE:
28 next_state = in ? IDLE : START;
29 START:
30 next_state = RXD;
31 RXD:
32 next_state = (cnt_byte==8)?PARITY:((cnt_byte>8)?WAIT:RXD); //cnt_byte不会大于8(直接进入WAIT状态),可省略内层判断
33 PARITY:
34 next_state = in ? STOP : WAIT;
35 WAIT:
36 next_state = in ? IDLE : WAIT;
37 STOP:
38 next_state = in ? IDLE : START;
39 default:
40 next_state = IDLE;
41 endcase
42 end
43
44 always@(posedge clk)begin
45 if(reset || next_state == IDLE || next_state == START)
46 cnt_byte <= 0;
47 else if(next_state==RXD)begin //数据data接受状态
48 out_byte_reg[cnt_byte] <= in; //8bit数据寄存,利用计数器当位置索引
49 cnt_byte <= cnt_byte+4'd1;
50 end
51 end
52
53 assign re = reset || next_state == IDLE || next_state == START; //IDLE或START为新一轮数据传输开始,奇偶校验清零信号
54 parity u_parity(
55 .clk(clk),
56 .reset(re),
57 .in(in),
58 .odd(odd)
59 );
60
61 assign done = (current_state==STOP)&&~odd; //因为在STOP状态又进行奇校验反转了一次,odd取反
62 assign out_byte = done?out_byte_reg:8'bz;
63
64 endmodule