实验内容
1、设计“1101”序列检测的状态转换图。
2、并转串模块设计,利用移位寄存器原理,setd 端上升沿将 8 位输入数据
同时锁存到移位寄存器中,在后续的 8 个时钟周期内将 8 位数据逐次移位
输出。
3、调用并转串输出模块,使用 Verilog HDL 语言的行为描述方式实现一个
摩尔状态机,能检测一个 8 位的二进制数据中是否存在“1101”序列,如
果检测到该序列则指定的 LED 灯亮。
4、综合、实现、生成 bit 流,下载到开发板进行验证
原理图
模块划分
按钮防抖模块
module fangdou#(parameter width=8,T100hz=249999)
(input clk,
input reset,
input setd,
input key,
input[(width-1):0]data_in,
output dout
);
integer cnt_100hz;
reg clk_100hz;
wire debkey;
wire temp_out;
always @(posedge clk or posedge reset)//对板子上面的时钟分频用于按键防抖
if(reset)
cnt_100hz<=32'b0;
else
begin
cnt_100hz<=cnt_100hz+1'b1;
if(cnt_100hz==T100hz)
begin
cnt_100hz<=32'b0;
clk_100hz<=~clk_100hz;
end
end
reg key_rrr,key_rr,key_r;
always@(posedge clk_100hz or posedge reset)
if(reset)
begin
key_rrr<=1'b1;
key_rr<=1'b1;
key_r<=1'b1;
end
else
begin
key_rrr<=key_rr;// key_rrr等于前两个时钟上升沿的 key值
key_rr<=key_r;// key_rr等于前一个时钟上升沿的 key值
key_r<=key;//key_r等于当前时钟上升沿的key,当按键抖动时
end
assign debkey=key_rrr & key_rr & key_r;//当且仅当key_rrr,key_rr,key_r都等于1的时候debkey才等与一
//按键发生抖动难以满足三者同时为1的条件,所以可以有效进行防抖
bing_to_chuan #(width) btc(.btn_clk(debkey),.reset(reset),.en(setd),.data_in(data_in),.dout(temp_out));
/*调用bing_to_chuan模块,将输入的数据进行锁存。debkey为按动按键手动产生的时钟,每按一次按键产生一次上升沿。
每次按下按钮,bing_to_chuan模块就会截取一位锁存的数据传入zhuangtaiji模块,即完成对并行输入的数据,进行串行
检测的要求,按下按钮8次后才会将当前锁存的数据全部检测完*/
zhuangtaiji ztj( .clk(debkey),.reset(reset),.din(temp_out),.dout(dout));
//根据串行传入的数据进行检测1101序列的模块
endmodule
锁存数据、并转串模块
module bing_to_chuan#(parameter width=8)
(input btn_clk,input reset,input en, input[(width-1):0]data_in, output reg dout);
reg [(width-1):0] temp_d;
always@(posedge en or posedge btn_clk or posedge reset)
begin
if(en)//en有效时传入数据,将数据锁存在temp_d中
temp_d=data_in;
else if(reset)//重置信号
dout=1'b0;
else
begin
dout=temp_d[0];
temp_d={1'b0,temp_d[(width-1):1]};
/*对信号进行移位,每当btn_clk到达上升沿,也即按下按钮,
取出temp_d的一位数据传入状态转换模块*/
end
end
endmodule
状态转移判断序列模块
module zhuangtaiji(
input clk, input reset, input din, output reg dout);
parameter s0=3'b000;
parameter s1=3'b001;
parameter s2=3'b010;
parameter s3=3'b011;
parameter s4=3'b100;//状态声明
reg [2:0] current_state,next_state;//现态与次态
always@(posedge clk or posedge reset)
begin
if(reset)//重置
begin
current_state<=s0;
end
else
current_state<=next_state;
end
always@(current_state or din or reset)//状态转换判断
begin
if(reset)//重置
next_state=s0;
else
begin
case(current_state)
//对现态以及传入的数据进行判断后,确定次态
//具体转换逻辑详见原理图
s0:
if(din==1'b1) next_state=s1; else next_state =s0;
s1:
if(din==1'b1) next_state=s2; else next_state =s0;
s2:
if(din==1'b0) next_state=s3; else next_state=s2;
s3:
if(din==1'b1) next_state=s4; else next_state=s0;
s4:
if(din==1'b1) next_state=s1; else next_state=s0;
default: next_state=s0;
endcase
end
end
always@(reset or next_state)//判断输出
begin
if(reset)//重置
dout=0;
else
begin
if(next_state == s4)dout=1;
//次态等于状态s4时,即检测到1101序列,输出信号赋值1
else
dout=0;
//次态不等于状态s4说明未检测到序列1101,输出信号赋值0
end
end
endmodule