赞
踩
1、根据以下描述功能用verilog编写一段代码,并用状态机来实现该功能。
(1)状态机:实现一个测试过程,该过程包括启动准备状态、启动测试、停止测试、查询测试结果、显示测试结果、测试结束返回初始化6个状态;用时间来控制该过程,90秒内完成该过程;
(2)描述状态跳转时间;
(3)编码实现。
2. 画出可以检测10010串的状态图, 并用verilog编程实现之。
file->new project wizard…
项目就建立好了!!!
//15s脉冲信号 module time_count( input wire clk, //时钟,50MHZ input wire rst_n, //复位信号,下降沿有效,negative output wire sec_15//15s输出一个脉冲信号 ); parameter MAX_NUM = 30'd749_999_999;//记最大数15s,750_000_000次 reg [29:0] cnt_15;//计数寄存器 reg sec_15_r; //0.5s计时器 always@(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_15 <= 25'd0; end else if(cnt_15 == MAX_NUM)begin cnt_15 <= 25'd0; end else begin cnt_15 <= cnt_15 + 1'd1; end end //0.5s脉冲信号 always@(posedge clk or negedge rst_n)begin if(!rst_n)begin sec_15_r <= 1'b0; end else if(cnt_15 == MAX_NUM)begin sec_15_r <= 1'b1; end else begin sec_15_r <= 1'b0; end end assign sec_15 = sec_15_r;//当右边改变,立马赋值给左边 assign和always并行 endmodule
module fsm( input clk, input rst_n, input wire sec_15 //15s输出一个脉冲信号 ); reg [2:0] cstate; //现态 reg [2:0] nstate; //次态 //状态划分 localparam s1 = 0; //启动准备状态 localparam s2 = 1; //启动测试 localparam s3 = 2; //停止测试 localparam s4 = 3; //查询测试结果 localparam s5 = 4; //显示测试结果 localparam s6 = 5; //初始化 //第一段:现态跟随次态,时序逻辑,非阻塞赋值 always@(posedge clk or negedge rst_n)begin if(!rst_n) cstate <= s6;//复位键被按下,当前状态设置为初始化 else cstate <= nstate; //下一次状态赋值给当前状态 end //第二段:组合逻辑,阻塞赋值 always@(*)begin if(!rst_n) begin nstate = s6; end else case(cstate) s6: begin if(sec_15 == 1'b1) //该状态持续时间为1s,1s后,下一次状态更改为led1亮 nstate = s1; else nstate = s6; end s1: begin if(sec_15 == 1'b1) nstate = s2; else nstate = s1; end s2: begin if(sec_15 == 1'b1) nstate = s3; else nstate = s2; end s3: begin if(sec_15 == 1'b1) nstate = s4; else nstate = s3; end s4: begin if(sec_15 == 1'b1) nstate = s5; else nstate = s4; end s5: begin if(sec_15 == 1'b1) nstate = s6; else nstate = s5; end default: ; endcase end endmodule
module top_fsm( input wire clk, input wire rst_n ); wire sec_15;//将两个模块的信号连接起来 //例化计时器模块 time_count inst_time_count( .clk (clk ),//时钟,50MHZ .rst_n (rst_n ),//复位信号,下降沿有效,negative .sec_15 (sec_15) //15s输出一个脉冲信号 ); //例化状态机模块 fsm inst_fsm( .clk (clk ),//时钟,50MHZ .rst_n (rst_n ),//复位信号,下降沿有效,negative .sec_15 (sec_15) //15s脉冲信号 ); endmodule
module key_debounce( input wire clk, input wire rst_n, input wire key, output reg flag, //判断抖动是否消除的标志信号,0为抖动,1为抖动结束 output reg key_value //消抖后稳定的按键值给到蜂鸣器模块和LED模块 ); //定义20ms延迟计数器,0.2s,1_000_000次 reg [19:0] delay_cnt; //寄存依次key的值用来判断按键是否消抖成功 reg key_reg; //按下按键20ms延时计数器 always@(posedge clk or negedge rst_n)begin if(!rst_n) begin key_reg <= 1'b1; //复位信号,设置按键无效 delay_cnt <= 1'b0; //计数器设置为0 end else begin key_reg <= key; if(key_reg ^ key) //当这一次key值和上一次key值不一样,证明正在抖动 delay_cnt <= 20'd1_000_000; //延迟时间20ms else if(delay_cnt > 0) delay_cnt <= delay_cnt - 1; //没有抖动,开始20ms倒计时 else delay_cnt <= 1'b0; end end //根据延时计数器获取按键状态以及按键值 always@(posedge clk or negedge rst_n)begin if(!rst_n) begin flag <= 1'b0; //复位信号,设置信号标志为抖动 key_value <= 1'b1; //设置抽样值为1 end else begin if(delay_cnt == 20'd1) //倒计时1_000_000到1 begin flag <= 1'b1; key_value <= key; //稳定20ms后将key值给到key_value end else begin flag <= 1'b0; key_value <= key_value; //20ms内先不取样 end end end endmodule
module fsm_10010( input clk, input rst_n, input [1:0] key, output wire [3:0] led ); parameter MAX_NUM = 24'd9_999_999;//0.2s计时器 parameter T = 4'd10;//2s,100_000_000次 reg [2:0] cstate; //现态 //状态划分 localparam state_0 = 0; //初始状态 localparam state_1 = 1; //按下1 localparam state_10 = 2; //按下10 localparam state_100 = 3; //按下100 localparam state_1001 = 4; //按下1001 localparam state_10010 = 5; //按下10010 reg [3:0] cnt = 0; //计时器赋初值为0 reg [23:0] cnt_02 = 0; reg time_flag;//计时标志,1:开始计时,0:结束计时 reg [3:0] led_r; //0.2计数器模块 always@(posedge clk or negedge rst_n)begin if(!rst_n) cnt_02 <= 1'b0; //按下复位键,清零 else if(cnt_02 == MAX_NUM) cnt_02 <= 1'b0; else cnt_02 <= cnt_02 + 1'b1; end //2s计数器模块 always@(posedge clk or negedge rst_n)begin if(!rst_n) cnt <= 1'b0;//按下复位键,清零 else if(time_flag == 1'b1)begin//开始计时 if(cnt_02 == MAX_NUM)begin if(cnt < T)begin cnt <= cnt + 1'b1; end else begin cnt <= 1'b0;//cnt计数达到最大就清空 end end else begin cnt <= cnt;//其余时间保持 end end else begin cnt <= 1'b0;//不计时,cnt清空 end end //状态切换模块 always@(posedge clk or negedge rst_n)begin if(!rst_n) begin cstate <= state_0; end else case(cstate) state_0: begin if(key[1] == 1'b1) //该状态持续时间为1s,1s后,下一次状态更改为led1亮 cstate <= state_1; else if(key[0] == 1'b1) cstate <= state_0; else cstate <= state_0; end state_1: begin if(key[0] == 1'b1) cstate <= state_10; else if(key[1] == 1'b1) cstate <= state_0; else cstate <= state_1; end state_10: begin if(key[0] == 1'b1) cstate <= state_100; else if(key[1] == 1'b1) cstate <= state_0; else cstate <= state_10; end state_100: begin if(key[1] == 1'b1) cstate <= state_1001; else if(key[0] == 1'b1) cstate <= state_0; else cstate <= state_100; end state_1001: begin if(key[0] == 1'b1)begin cstate <= state_10010; time_flag <= 1'b1;//开始计时 end else if(key[1] == 1'b1) cstate <= state_0; else cstate <= state_1001; end state_10010: begin if(cnt == T)begin cstate <= state_0; time_flag <= 1'b0;//结束计时 end else cstate <= state_10010; end default: ; endcase end //第三段:跟随状态输出 按1 led2 闪 按0 led1 闪 always@(posedge clk or negedge rst_n)begin if(!rst_n) led_r <= 4'b0001; else case(cstate) state_1: led_r <= 4'b0010; state_10: led_r <= 4'b0001; state_100: led_r <= 4'b0001; state_1001: led_r <= 4'b0010; state_10010:if(cnt_02 == 24'd4_999_999) led_r <= 4'b1111; else if(cnt_02 == MAX_NUM) led_r <= 4'b0000; else led_r <= led_r; default : led_r <= 4'b0001; endcase end assign led = led_r; endmodule
module top_fsm_10010( input wire clk, input wire rst_n, input wire [1:0] key, output wire [3:0] led ); wire [1:0] flag; wire [1:0] key_value; //例化按键KEY1 key_debounce inst_key_debounce( .clk (clk ), .rst_n (rst_n ), .key (key[0] ), .flag (flag[0] ), //判断抖动是否消除的标志信号,0为抖动,1为抖动结束 .key_value(key_value[0]) //消抖后稳定的按键值给到蜂鸣器模块和LED模块 ); //例化按键KEY2 key_debounce inst_key_debounce1( .clk (clk ), .rst_n (rst_n ), .key (key[1] ), .flag (flag[1] ), //判断抖动是否消除的标志信号,0为抖动,1为抖动结束 .key_value(key_value[1]) //消抖后稳定的按键值给到蜂鸣器模块和LED模块 ); //例化状态机 fsm_10010( .clk (clk ), .rst_n(rst_n ), .key ({~key_value[1]&&flag[1],~key_value[0]&&flag[0]}), .led (led) ); endmodule
按key2 是1 , 按key1 是0, 1的时候led1亮,0的时候led0亮
主要思想是对状态的判断,判断完后,再赋予对应的输出,和实训做的密码锁类似。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。