题目:
序列检测状态机图:
注意:收到1001001时,只能算检测到一组
初始状态是S0,若当din = 1 时,跳转到S1; 若 din = 0 时,不跳转,保持原状态;
在S1状态时:若当din = 0 时,跳转到 S2 ; 若 din = 1 时,不跳转,保持原状态;
在S2状态时:若当din = 0 时,跳转到 S3 ; 若 din = 1 时,跳转到S1;
在S3状态时:din前面已经收到了100了,此时在S3状态时,若din 收到了1 ,就成功检测到了1001 序列,此时也要跳转到S0,便有后续重新检测下一轮序列;若din = 0 时,跳转到S0,重新开始检测下一个序列。
也就是说,当在S3状态时,不管din收到0还是1,都要跳转到S0,产生dout条件是 在S3状态且,din = 1。
画状态时,先画出能够明确跳转到下一个状态和条件,然后再考虑不跳转或跳回原上一个状态等。
代码:
1 module state_test( 2 clk, 3 rst_n, 4 din, 5 dout 6 ); 7 8 parameter S0 = 3'b000; 9 parameter S1 = 3'b001; 10 parameter S2 = 3'b010; 11 parameter S3 = 3'b100; 12 13 input clk; 14 input rst_n; 15 input din; 16 17 output dout; 18 19 reg dout; 20 21 wire S02S1_start; 22 wire S12S2_start; 23 wire S22S3_start; 24 wire S22S1_start; 25 wire S32S0_start; 26 27 reg[4-1:0] state_c; 28 reg[4-1:0] state_n; 29 30 //第一段,状态跳转 31 always @(posedge clk or negedge rst_n)begin 32 if(!rst_n)begin 33 state_c <= S0; 34 end 35 else begin 36 state_c <= state_n; //将下一个状态赋给当前状态 37 end 38 end 39 40 //第二段:组合逻辑always模块,描述状态转移条件判断 41 always @(*)begin 42 case(state_c) 43 44 S0:begin 45 if(S02S1_start)begin 46 state_n = S1; 47 end 48 else begin 49 state_n = state_c; 50 end 51 end 52 53 S1:begin 54 if(S12S2_start)begin 55 state_n = S2; 56 end 57 else begin 58 state_n = state_c; 59 end 60 end 61 62 S2:begin 63 if(S22S3_start)begin 64 state_n = S3; 65 end 66 else if(S22S1_start)begin 67 state_n = S1; 68 end 69 else begin 70 state_n = state_c; 71 end 72 end 73 74 S3:begin 75 if(S32S0_start)begin 76 state_n = S0; 77 end 78 else begin 79 state_n = state_c; 80 end 81 end 82 83 default : begin 84 state_n = S0; 85 end 86 endcase 87 end 88 89 //第三段:设计转移条件 90 assign S02S1_start = state_c == S0 && din == 1; 91 assign S12S2_start = state_c == S1 && din == 0; 92 assign S22S3_start = state_c == S2 && din == 0; 93 assign S22S1_start = state_c == S2 && din == 1; 94 assign S32S0_start = state_c == S3 && (din == 0 || din == 1); //注意优先级,需将后面的或运算符用括号括起来 95 96 //第四段:同步时序always模块,格式化描述寄存器输出(可有多个输出) 97 always @(posedge clk or negedge rst_n) begin 98 if(!rst_n)begin 99 dout <= 0; 100 end 101 else if(state_c == S3 && din == 1)begin // S32S0_star && din == 1 102 dout <= 1; 103 end 104 else begin 105 dout <= 0; 106 end 107 end 108 109 endmodule
测试代码:
1 module state_sim; 2 3 reg clk; 4 reg rst_n; 5 reg din; 6 7 wire dout; 8 9 parameter CLK_CYCLE = 10; 10 11 initial begin 12 clk = 0; 13 forever begin 14 #(CLK_CYCLE/2); 15 clk = ~clk; 16 end 17 end 18 19 initial begin 20 rst_n = 0; 21 #1; 22 #(CLK_CYCLE*5); 23 rst_n = 1; 24 end 25 26 initial begin 27 #1; 28 din = 0; 29 #(CLK_CYCLE*10); 30 din = 1; 31 #(CLK_CYCLE); 32 33 din = 0; 34 #(CLK_CYCLE); 35 36 din = 0; 37 #(CLK_CYCLE); 38 39 din = 1; 40 #(CLK_CYCLE); 41 42 din = 0; 43 #(CLK_CYCLE); 44 45 din = 0; 46 #(CLK_CYCLE); 47 48 din = 1; 49 #(CLK_CYCLE); 50 51 repeat(100)begin 52 din = $urandom_range(0,1); 53 #(CLK_CYCLE); 54 end 55 end 56 57 state_test u1_inist( 58 .clk(clk), 59 .rst_n(rst_n), 60 .din(din), 61 .dout(dout) 62 ); 63 64 endmodule
仿真波形:
quartus 综合出来的状态图:
转移条件: