【Verilog HDL实践】序列检测实现
使用芯片:Altera Cyclone® IV EP4CE22F17C6N FPGA
开发工具:Quartus Ⅱ
开发项目:六、设计一个“10010”串行数据检测器。当检测到数据串时,Y输出高电平,其余时间Y输出低电平。输入X:000101010010011101001010100010101001001110100101010101。
序列检测分析
使用状态机思想
共5种状态:
- state_d:初始状态,当第一个输入非1 或 检测到1000等数据时的状态。
- 状态1:检测到‘1’,当前输入为0时跳转到状态2,否则保持原状态。
- 状态2:检测到‘10’,当前输入为0时跳转到状态3,否则跳转到状态1。
- 状态3:检测到‘100’,当前输入为1时跳转到状态4,否则跳转到state_d。
- 状态4:检测到‘1001’,当前输入为0时跳转到状态2,并输出高电平;否则跳转到状态1。
这里没有引入状态’10010‘,因为个人觉得不是很有必要,状态4检测到0时已经输出为高,切换到状态5后貌似存在冗余。
代码展示
/*
Sequence Detection
功能描述:
序列检测 ‘10010’串行数据检测器
引脚描述:
输入:50MHz时钟
输出:led[0]切换代表序列值切换、led[1]亮代表检测到‘10010’
状态分析:
‘1’、’10‘、’100‘、’1001‘、‘等待状态’
*/
module Sequence_detection(led, clk);
input clk;
output reg[1:0] led = 2'b00;
parameter state1=3'b000, state2=3'b001, state3=3'b010, state4=3'b011, state_d=3'b111;//状态定义
parameter[31:0] duration = 32'd12500000; //timer:500ms
reg[1:0] current_state = state_d, next_state = state_d;
reg[31:0] counter = 32'b0;
reg delay_flag = 1'b0;
reg[53:0] checking_value = 54'b00010101_00100111_01001010_10001010_10010011_10100101_010101;
reg[5:0] checking_position=6'b0;
parameter sequence_length = 54;
//状态切换
always@(posedge clk) begin
current_state <= next_state;
counter <= counter + 1'b1;
if(counter >= duration-1) begin
counter <= 0;
led[0] <= ~led[0];
delay_flag <= ~delay_flag;
end
end
//下个状态变换
always@(posedge delay_flag) begin
led[1] <= 1'b0;
checking_position <= checking_position + 1;
if(checking_position >= sequence_length-1)
checking_position <= 0;
case(current_state)
state_d: begin
if(checking_value[checking_position])
next_state <= state1;
end
state1: begin //1->10 / 11
if(!checking_value[checking_position])
next_state <= state2;
end
state2: begin //10->100 / 101
if(!checking_value[checking_position])
next_state <= state3;
else
next_state <= state1;
end
state3: begin //100->1001 / 1000
if(checking_value[checking_position])
next_state <= state4;
else
next_state <= state_d;
end
state4: begin //1001->10010 / 10011
if(!checking_value[checking_position]) begin
next_state <= state2;
led[1] <= 1'b1;
end
else
next_state <= state1;
end
endcase
end
endmodule
代码中引入一个500ms的定时器是为了确定代码移植到开发板后正常,通过观察灯的变换可以检测是否正确。
代码中检测到序列后使用非阻塞赋值,导致输出为高的时刻有所滞后,可以修改赋值方式实现输出时刻调整。
时序测试
这里将duration,即定时器改为4倍频,查看输出情况,可以看到,检测完第12个序列值后输出变为1(前12个值:000101010010)
这里我第一次直接将第二个always的触发源换为clk后时序输出不对,感觉应该是和第一个冲突了?(有时候老是有些莫名其妙的问题)
烧到板子上也是没有问题的