实验报告
用状态机实现序列检测器实验
一、实验目的
1.用Verilog HDL描述有限状态机电路。 2.IPCORE的概念与设计。 二、实验内容
1.应用有限状态机的设计思路,检测从FPGA片上ROM读出的串行数据是否是特定的数据。
2.每个人需要检测的数据是所用的电脑编号+200后转换的8位二进制数。 三、实验要求
1.拟用按键、拨动开关实现系统的时钟,复位信号的输入。
2.一个7段数码显示译码器作为检测结果的输出显示,如果串行序列为”100101”,显示A,否则显示b(系统需要设计一个7段数码显示译码器模块)仍使用消抖模块,对由按键输入的时钟进行消抖处理。
3.读取的串行数据为rom中固化的一个宽度为1bit,深度为16bits的数据。 四、设计思路
软件的设计框图如下,该实验可以分为几个模块,rom数据读出模块,串行检测模块,数码管显示模块,顶层模块。
输入的clk为按键消抖后输出的数据,按下一次检测一次,在时钟的上升沿读出数据,时钟的下降沿检测数据,串行模块输出的4bits的数据,直接送给数码管译码模块,译码输
;
.
出。
五、设计原理
1.ROM IP核的生成
首先在ISE自己的工程中新建一个块内存,Block Memory Generator,配置深度为16,宽度为1bit,选择生成的类型为单端ROM,然后选择一个已经编写好的memory初始化文件。
Memory初始化文件,编写coe文件:这里我要写入的是226,所以二进制是11100010,写入的内容如下,:
memory_initialization_radix=10;
memory_initialization_vector=1 1 1 0 0 0 1 1 1 0 1 0 1 0 1 0; 保存并选择载入。 2. 读取rom中的数据
根据时钟上升沿读取数据,所以可以写出rom读的代码,代码如下: module read_rom(clk,da,rst); input clk; input rst; output da; reg[3:0] counter;
always@(posedge clk or posedge rst) begin if(rst)
counter<=1'b0; end
else counter<=counter+1'b1;
;
.
data_rom u1(
.clka(clk), // input clka
.addra(counter), // input [3 : 0] addra .douta(da) // output [0 : 0] douta );
编写仿真激励文件,得到如下波形,分析可以知道,时钟上升沿数据被读取,读取的数据与我们在配置文件中写入的相同。
3. 串行检测
本人的编号为226,转换为二进制数为11100010,根据二进制数,画出状态转移图,状态转移图如下:
根据状态转移图,编写verilog代码,代码如下:
//检测:11100011 module ser_read( input clk, input r_bit, input rst,
;
.
output reg out_flag );
reg[3:0] status;
always@(negedge clk,posedge rst)begin if(rst==1)begin status<=4'b0; out_flag<=1'b0; end else begin case(status) 4'd0:begin if(r_bit)
status<=4'd1; out_flag<=1'b0; end 4'd1: if(r_bit)
status<=4'd2; else
status<=4'd0; 4'd2: if(r_bit)
status<=4'd3; else
status<=4'd0; 4'd3: if(!r_bit)
status<=4'd4; 4'd4: if(!r_bit)
status<=4'd5;//11100
;
.
else
status<=4'd0; 4'd5: if(!r_bit)
status<=4'd6;//111000 else
status<=4'd0;//111001 4'd6: if(r_bit)
status<=4'd7;//1110001 else
status<=4'd0;//1110000 4'd7: if(r_bit)begin
status<=4'd0;//11100011 out_flag<=1'b0; end else begin
status<=4'd0;//11100010 out_flag<=1'b1; end endcase end end Endmodule
编写仿真激励文件,得到如下波形,因为rom数据是上升沿读取,所以串行检测是在下降沿完成的,通过波形可以看出,当检测到11100010是,out_flag输出为高,反之输出为低,满足要求。
4.
数码管显示
;
.
数码管显示代码如下:(静态数码管) module decled(ledin,ledout); input ledin; output[6:0]ledout; reg[6:0]ledout; always@(ledin) begin case(ledin)
1'b1: ledout<=7'b1110111;//b 1'b0: ledout<=7'b0011111;//a default: ledout<=7'b0011111; endcase end endmodule 5.
顶层设计
顶层设计,按照之前的原理框图进行连接,连接完成后的代码如下: module top(clk_50m,reset,data,clk_key); input clk_50m,reset,clk_key; output [6:0]data; wire Pin_Out; wire flag_out;
debounce_module uut1 (.CLK(clk_50m), .RSTn(reset), .Pin_In(clk_key), .Pin_Out(Pin_Out)); //消抖
decled uut2 (.ledin(flag_out), .ledout(data)); //数码管显示
read_rom uut3 (.clk(Pin_Out), .da(da),.rst(reset)); //数据读取
schk uut4 (.r_bit(da), .clk(Pin_Out), .rst(reset), .out_flag(flag_out));//检测 endmodule
编写仿真激励文件,得到如下波形,可以看到当,按键按下8次后,数码管输出a,当数码管又按下16次后,数码管输出b,满足要求。
;
.
6. 引脚锁定
1.选择一个拨动开关为复位信号输入。 2.选择一个按键作为时钟输入。
3.50MHZ板上时钟为消抖计时时钟,引脚锁定是V10。 引脚锁定代码如下:
NET \"clk_key\" LOC = \"G9\" | CLOCK_DEDICATED_ROUTE = FALSE ; NET \"clk_50m\" LOC = V10; NET \"reset\" LOC = D14; NET \"data[6]\" LOC = U5; NET \"data[5]\" LOC = V5; NET \"data[4]\" LOC = R5; NET \"data[3]\" LOC = T5; NET \"data[2]\" LOC = U8; NET \"data[1]\" LOC = V8; NET \"data[0]\" LOC = N6;
六、思考题
1、什么是IPCORE?本次设计中ROM模块是如何进行设计输入的?
IP(Intellectual Property)在嵌入式FPGA设计中,指的是某些设计好的模块,分为软件模块和硬件模块。这些模块,一般都是已经测试好,所有功能完善的,由一些用户自己设计的。有些模块是免费的,也有收费的模块。所有用户都可以将这些IP核(IP Core)导入到自己的工程中,同样,所有用户也都可以定制自己的IP核。本次设计中的rom的输入是通过.coe文件在配置ip核的使用进行指定的,编写规则按照xilinx官方给出的文档进行定义。
2、说明状态机代码表达的是什么类型的状态机,它的优点是什么?详述其功能和对序列数检测的逻辑过程;
由于状态机输出与输入有关,所以该状态机为Mealy状态机。状态机在系统时钟的控制下,电路按照预先设定的状态运行,有良好的同步时序,较好的解决了竞争冒险和毛刺现象。状态的的结构使其在一个时钟周期内可以完成许多并行的运算和控制操作,
;
.
与Moore有限状态机不同,Mealy有限状态机的输出不单与当前状态有关,而且与输入信号的当前值有关,Mealy有限状态机的输出直接受输入信号的当前值影响,而输入信号可能在一个时钟周期内任意时刻变化,这使得Mealy有限状态机对输入的响应发生在当前时钟周期,比Moore有限状态机对输入信号的响应要早一个周期。 七、实验体会
通过用状态机实现序列检测器的设计实验,初步熟悉和掌握了IPCORE的使用。同时运用状态机实现序列检测器的设计,进一步掌握了课堂上所学到的知识,但同时充分的感觉到了自己的不足之处,今后一定要加强自己弱势方面的学习,用心学好EDA教科书上的知识,并抽时间在课外进行深入地学习,相信下次试验情况会有很大程度的改观。
;
.
附录
顶层模块激励文件如下: module test_top;
initial begin
// Initialize Inputs clk_50m = 0; reset = 0; clk_key = 0;
// Instantiate the Unit Under Test (UUT) top uut ( );
.clk_50m(clk_50m), .reset(reset), .data(data), .clk_key(clk_key) // Outputs wire [6:0] data; // Inputs reg clk_50m; reg reset; reg clk_key;
#10 reset = 1; #10 reset = 0;
// Wait 100 ns for global reset to finish #10 clk_50m = 0;clk_key = 1;; forever begin
;
.
#10 clk_key=~clk_key; end
end
// Add stimulus here
endmodule
;
因篇幅问题不能全部显示,请点此查看更多更全内容