题目:用状态机检测串行输入单bit序列ser_in,每当已输入序列为7的倍数时,拉高信号flag_7。其中输入时钟为clk 上升沿采样,复位信号为rst_n,低电平有效
这题思路借鉴于模三检测器:使用verilog代码,设计电路,判断输入序列能否被三整除,能的话输出1,不能的话输出0。
模三检测器
原理
判断输入序列的序列监测器,一个输入被三除,对于余数来说只有三种可能,分别为0、1、2(整除,余数为1,余数为2),假如0、1、2对应三种状态,加上IDLE状态,我们需要四个状态来表示模三检测器的状态机(换到模七就是八个状态)。
关键点
输入序列是一边移位、一边输入,假如第一位输入1,第二位输入0,在输入第二位的时候,当前输入序列表示为10,即先输入的1移动到了输入序列的最高位。
模三检测器的本质,是一个结合了当前状态和输入序列,来判断输出的mealy型状态机(输出与当前状态和输入都有关)
所以具体的状态机转换为:
当前态余数 | 输入 | 次态余数 | 输出 |
---|---|---|---|
0 | 1 | 1 | 0 |
0 | 0 | 0 | 1 |
1 | 0 | 2 | 0 |
1 | 1 | 0 | 1 |
2 | 0 | 1 | 0 |
2 | 1 | 2 | 0 |
状态转换图
代码
// 模三
module mod3_check(
input clk,
input rst_n,
input data,
output test
);
parameter IDLE = 2'b00;
parameter s1 = 2'b01;
parameter s2 = 2'b10;
parameter s3 = 2'b11;
reg [1 : 0] state;
reg [1 : 0] nstate;
always@(posedge clk or negedge rst_n) begin
if(rst_n == 1'b1)
state <= IDLE;
else
state <= nstate;
end
always(*) begin
case(state)
IDLE : nstate = data ? s1 : s3;
s1 : nstate = data ? s3 : s2;
s2 : nstate = data ? s2 : s1;
s3 : nstate = data ? s1 : s3;
default nstate = IDLE;
endcase
end
assign test = state == s3 ? 1 : 0;
endmodule
模七检测器
用状态机检测串行输入单bit序列ser_in,每当已输入序列为7的倍数时,拉高信号flag_7。其中输入时钟为clk 上升沿采样,复位信号为rst_n,低电平有效
状态转换图
代码
// 模七
module mod7_check(
input clk,
input rst_n,
input data,
output test
);
parameter IDLE = 3'b000;
parameter s1 = 3'b001;
parameter s2 = 3'b010;
parameter s3 = 3'b011;
parameter s4 = 3'b100;
parameter s5 = 3'b101;
parameter s6 = 3'b110;
parameter s7 = 3'b111;
reg [1 : 0] state;
reg [1 : 0] nstate;
always@(posedge clk or negedge rst_n) begin
if(rst_n == 1'b1)
state <= IDLE;
else
state <= nstate;
end
always(*) begin
case(state)
IDLE : nstate = data ? s1 : s7; // 1 -> s1 , 0 -> s7
s1 : nstate = data ? s3 : s2; // 11 -> s3 , 10 -> s2
s2 : nstate = data ? s5 : s4; // 101 -> s5 , 100 -> s4
s3 : nstate = data ? s7 : s6; // 111 -> s7 , 110 -> s6
s4 : nstate = data ? s2 : s1; // 1001 -> s2 , 1000 -> s1
s5 : nstate = data ? s4 : s3; // 1011 -> s4 , 1010 -> s3
s6 : nstate = data ? s6 : s5; // 1101 -> s6 , 1100 -> s5
s7 : nstate = data ? s1 : s7; // 1111 -> s1 , 1110 -> s7
default nstate = IDLE;
endcase
end
assign test = state == s7 ? 1 : 0;
endmodule