用状态机实现序列检测器
用状态机实现序列检测器
1 实验目的
掌握利用有限状态机实现一般时序逻辑分析的方法,了解一般状态机的设计与应用。
2 实验内容
设计一序列检测器并在 SmartSOPC 实验箱上进行硬件测试。利用 Quartus ||软件进行设
计、仿真验证,最后进行引脚锁定并完成硬件测试。用 K3 控制复位;K4 控制状态机的时
硬 对模块的各端口说明如下:
clock
系统时钟输入(48MHz)
key[3..0]
按键输入
disp[3..0]
序列检测器检测结果输入(显示于数码管 8)
sda
串行序列码输出
clkout
序列检测器状态机时钟输出
rstout
序列检测器复位信号输出
dat[7..0]
检测预置数输出
led7..0]
LED 输出
239
seg[2]
167
dig[1]
159
key[0]
121
seg[3]
168
dig[2]
162
key[1]
122
seg[4]
165
dig[3]
161
key[2]
123
seg[5]
166
dig[4]
236
key[3]
124
seg[6]
163
dig[5]
237
clock
28
(6)将 schk_top.bdf 设置为顶层实体,对该工程进行全程编译处理,若在编译过程中发现 错误,则找出错误并更正错误,直至编译成功为止。 (7)硬件连接、下载程序。
//显示 5
4'h6:seg_r = 8'h82;
//显示 6
4'h7:seg_r = 8'hf8;
//显示 7
星
4'h8:seg_r = 8'h80; 4'h9:seg_r = 8'h90;
//显示 8
红
—袁 //显示 9
4'ha:seg_r = 8'h88;
言 //显示 a
4'hb:seg_r = 8'h83;
//时钟分频计数器 //内部寄存器
//消抖寄存器 //数码管扫描计数器
//数码管扫描显存 //分频时钟,用于消抖和扫描 //按键消抖输出
assign dat = dat_r; assign led = ~led_r; assign seg = seg_r; assign dig = dig_r;
//时钟分频部分
buff <= dout1 | dout2 | dout3; end
assign key_edge = ~(dout1 | dout2 | dout3) & buff;
always @(posedge clock)
begin
星
if(key_edge[0]) cnt2 <= cnt2 + 1'b1;
红 袁 —
5 实验程序
模块 1 为:
module schk_test(clock,key,sda,clkout,rstout,dat,disp,led,seg,dig);
//外接 I/O 口
input clock;
//系统时钟
input[3:0]key;
//按键输入
output[7:0]led;
//输出接 LED
parameter
S0 = 4'd0, S1 = 4'd1, S2 = 4'd2, S3 = 4'd3, S4 = 4'd4, S5 = 4'd5, S6 = 4'd6, S7 = 4'd7, S8 = 4'd8;
//状态机参数
assign disp = disp_r;
//输出检测结果
星
红
always @(posedge clk or negedge rst)
input
sda;
input
clk;
input
rst;
input[7:0]dat;
//序列检测模块 //串行序列码输入 //时钟信号输入 //复位信号输入
//输入待检测预置数
output[3:0] disp;
//检测结果输出
reg[3:0] disp_r; reg[3:0] state;
//检测结果输出寄存器 //状态机寄存器
seg[7..0]
数码管段输出
dig[7..0]
数码管位输出
4 实验步骤
(1)启动 Quartus||建立一个空白工程,然后命名为 schk_top.qpf。
(2)新建 VerilogHDL 源程序文件 schk_test(测试信号生成模块),输入程序代码并保存,
将 Verilog HDL 源程序文件转换成图形文件。若在编译过程中发现错误,则找出并更正错误, 直至编译成功为止。 (3)新建 Verilog HDL 源程序文件 schk_v(序列检测模块),输入程序代码并保存,将 Verilog HDL 源程序文件转换成图形文件。若在编译过程中发现错误,则找出并更正错误,直至编 译成功为止。 (4)新建图形设计文件命名为 schk_top.bdf 并保存,其模块原理图如下:
//串行序列码输出
//数码管扫描显示部分 always @(posedge clock) begin
if(div_clk) cnt3 <= cnt3 + 1'b1;
end
//定义上升沿触发进程
always @(posedge clock)
begin
if(div_clk)
begin
星
case(cnt3) 3'd0:disp_dat = data[7:4];
case(disp_dat)
//七段译码
4'h0:seg_r = 8'hc0;
//显示 0
4'h1:seg_r = 8'hf9;
//显示 1
4'h2:seg_r = 8'ha4;
//显示 2
4'h3:seg_r = 8'hb0;
//显示 3
4'h4:seg_r = 8'h99;
//显示 4
4'h5:seg_r = 8'h92;
言 码做记忆分析,直到在连续检测中所收到的每一位二进制码都与预置序列码对应相同。在检
语 测过程中,只要有一位不相等都将回到初始状态重新开始检测,不考虑重叠的可能。
设计 (2)为了配合硬件测试,需要设计一个测试模块(schk_test),该模块主要产生序列检测器 件 所需的时钟、复位、串行输入序列码及预置数等信号。
的数累增;再按 1 次 K1 后,按 K2 则数码管 1 显示的数累增,如此循环。
3 实验原理
星 红 (1)序列检测器可用于检测由二进制码组成的脉冲序列信号。当序列检测器连续收到一组
袁 串行二进制码后,如果这组序列码与检测器中预先设置的序列码相同,则输出 1,否则输出
— 0。这种检测的关键是必须收到连续的正确码,所以要求检测器必须对前一次接受到的序列
//选择第一个数码管显示
3'd4:dig_r = 8'b11110111;
//选择第二个数码管显示
3'd7:dig_r = 8'b11111110;
//选择第八个数码管显示
default:dig_r = 8'b11111111;
endcase
end
end
always @(disp_dat)
begin
if((key_edge[1])&&(cnt2==2'b01)) data[3:0] <= data[3:0] + 1'b1; end
//序列码低 4 位 //下降沿检测
always @(posedge clock)
//预置数高 4 位
begin if((key_edge[1])&&(cnt2==2'b10)) dat_r[7:4] <= dat_r[7:4] + 1'b1;
星 //按键 3 复位
assign clkout = buff[3];
红 //按键 4 时钟 袁
—
always @(posedge clock)
言
begin
语
if(key_edge[2])
计 //按键 3 复位
begin
设
硬件 data_shift = {1'b0,data};
led_r = 8'd0;
always @(posedge clock)
begin
if (count < 17'd120000)
begin
count <= count + 1'b1;
星
div_clk <= 1'b0; end
红 袁 —
else
言
begin
语
count <= 17'd0;
计
div_clk <= 1'b1;
设
end end
语//显示 b
4'hc:seg_r = 8'hc6;
计//显示 c
4'hd:seg_r = 8'ha1;
设 //显示 d
硬件 4'he:seg_r = 8'h86;
4'hf:seg_r = 8'h8e;