这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » (1602初探)hanshuyujifen的进程贴

共40条 2/4 1 2 3 4 跳转至
高工
2012-10-20 23:05:34     打赏
11楼
你这个占楼真狠

高工
2012-10-21 08:43:28     打赏
12楼
首页无水。。。。。。

工程师
2012-10-21 12:01:01     打赏
13楼
我也占楼备用......10

专家
2012-10-21 21:19:26     打赏
14楼
别占太多哦!!继续!!

高工
2012-12-08 12:41:27     打赏
15楼
按键控制数码管显示0到9

周期性检查按键,如果按键为低电平,则显示加1,否则不变。检测周期为200ms。
可以看出,虽然没有消抖动,但显示仍然不会出现乱跳的现象。
原因是,抖动一般发生在信号跳变的时候,我使用的是信号稳定的那段。间隔200ms检测,就相当于消抖动了。
但是这种方式处理按键比较累的,你可以按着试试。嘿嘿
以下是代码实现:
/*按键控制LED显示0-9,没有进行消抖*/

module keyled(sys_clk,sys_rstn,seg,smbit,keys);
input sys_clk;
input sys_rstn;
input [7:0]    keys;
output [7:0] seg,smbit;

reg [23:0]     delay_cnt;
reg [7:0]    seg;
reg [3:0]    disp_dat;
reg [4:0]    dataout_buf;

reg key_samp;            //用于按键边沿检测

always @(posedge sys_clk or negedge sys_rstn )
    begin
        if(!sys_rstn)
            delay_cnt<=24'b0;
        else
            begin
                if(delay_cnt == 24'd9999999)
                    delay_cnt <=0;
                else
                    delay_cnt = delay_cnt+1'b1;
            end
    end

always @(posedge sys_clk or negedge sys_rstn)
    begin
        if(!sys_rstn)
            disp_dat <=4'b0;
        else
            if(delay_cnt == 24'd9999999)
            begin
                if(!keys[0])
                    begin
                        if(disp_dat == 4'd9)
                            disp_dat <= 4'd0;
                        else
                            disp_dat <= disp_dat+1'b1;
                    end
                else
                    begin
                        disp_dat <= disp_dat;
                    end
            end
            else
                disp_dat <= disp_dat;
    end
       
always @(disp_dat)
begin
    case(disp_dat)
        4'h0    :seg = 8'hc0;
        4'h1    :seg = 8'hf9;
        4'h2    :seg = 8'ha4;
        4'h3    :seg = 8'hb0;
        4'h4    :seg = 8'h99;
        4'h5    :seg = 8'h92;
        4'h6    :seg = 8'h82;
        4'h7    :seg = 8'hf8;
        4'h8    :seg = 8'h80;
        4'h9    :seg = 8'h90;
        4'hA    :seg = 8'h88;
        4'hB    :seg = 8'h83;
        4'hC    :seg = 8'hc6;
        4'hD    :seg = 8'ha1;
        4'hE    :seg = 8'h86;
        4'hF    :seg = 8'h8e;
    endcase
end   

assign smbit = 8'b11111110;

endmodule

高工
2012-12-08 12:42:19     打赏
16楼
参照51FPGA的做法,对按键输入进行了简单的消抖
我感觉这个实验最困难的地方不是消抖,而是按键的边沿检测。按键边沿检测完全是版主的做法,看了日积月累之后才稍微理解为什么那样用。

这里的消抖就是简单的采样按键信号,然后延时20ms再进行一次采样。如果20ms之后还是低电平,说明单间按下了。实现起来并不困难,效果也不是很理想。偶尔还会有消不去的抖动发生。
实验现象是这样的,当按键按下去的时候11个LED灯全部反转。数码管数字在0-F自减循环显示。
以下就是实现的代码:

/*按键消抖*/
module keys_debounce(sys_clk,sys_rstn,seg,smbit,keys,leds);
input sys_clk;
input sys_rstn;
input [7:0]    keys;
output [7:0] seg,smbit;
output [10:0] leds;

wire [7:0]  smbit;
reg [10:0]    leds;
reg [19:0]     delay_cnt;
reg [7:0]    seg;
reg [3:0]    disp_dat;
reg [4:0]    dataout_buf;

//用于按键检测
wire key_scan;
wire key_low;
reg key_samp;
reg key_samp_r;
reg key_rst;
reg key_rst_r;


//按键脉冲边沿检测
always @(posedge sys_clk or negedge sys_rstn)
    begin
        if(!sys_rstn)
            key_samp <= 1'b1;
        else
            key_samp <= keys[0];
    end

always @(posedge sys_clk or negedge sys_rstn)
    begin
        if(!sys_rstn)
            key_samp_r <= 1'b1;
        else
            key_samp_r <= key_samp;
    end
assign key_scan = key_samp &(~key_samp_r);

//延时处理
always @(posedge sys_clk or negedge sys_rstn)
    begin
        if(!sys_rstn)
            delay_cnt <= 20'd0;
        else if(key_scan)
            delay_cnt <=20'd0;
        else
            delay_cnt <= delay_cnt+1'b1;
    end


always @(posedge sys_clk or negedge sys_rstn)
    begin
        if(!sys_rstn)
            key_rst <=1'b1;
        else
            begin
                if(delay_cnt <= 20'hfffff)
                    key_rst <= keys[0];
            end
    end
always @(posedge sys_clk or negedge sys_rstn)
    begin
        if(!sys_rstn)
            key_rst_r <=1'b1;
        else
            key_rst_r <=key_rst;
    end
assign key_low = key_rst &(~key_rst_r);
//反转LED
always @(posedge sys_clk or negedge sys_rstn)
    begin
        if(!sys_rstn)
            leds = 11'b0;
        else
            begin
                if(key_low)
                    leds <= ~leds;
                else
                    leds <= leds;
            end
    end
//数码管显示
always @(posedge sys_clk or negedge sys_rstn)
    begin
        if(!sys_rstn)
            disp_dat<= 8'b0;
        else    if(key_low)
            disp_dat<=disp_dat+1'b1;
        else
            disp_dat <=disp_dat;
    end
//数据显示
always @(disp_dat)
    begin
        case(disp_dat)
            4'h0    :seg = 8'hc0;
            4'h1    :seg = 8'hf9;
            4'h2    :seg = 8'ha4;
            4'h3    :seg = 8'hb0;
            4'h4    :seg = 8'h99;
            4'h5    :seg = 8'h92;
            4'h6    :seg = 8'h82;
            4'h7    :seg = 8'hf8;
            4'h8    :seg = 8'h80;
            4'h9    :seg = 8'h90;
            4'hA    :seg = 8'h88;
            4'hB    :seg = 8'h83;
            4'hC    :seg = 8'hc6;
            4'hD    :seg = 8'ha1;
            4'hE    :seg = 8'h86;
            4'hF    :seg = 8'h8e;
        endcase
    end   
assign smbit = 8'b11111110;
endmodule

高工
2012-12-08 15:16:18     打赏
17楼
循环语句使用练习。
一个简单的for循环。循环次数必须有限,在RTL中占用资源,循环越多占用越多。
另外,这种操作容易产生毛刺,很危险。。
所以for循环在硬件设计中常用计数器代替
/*使用FOR循环统计数据中包含0比特的个数*/
/*用于产生奇偶校验码*/
module counterzeros(a,Count);
parameter bitsize = 8;
input [bitsize:0] a;
output [3:0] Count;

reg [3:0] Count;
reg [3:0] Count_Aux;

integer i;

always @(a)
    begin
        Count_Aux =4'b0;
        for(i=0;i<bitsize;i = i+1)
        begin
            if(!a[i])
                Count_Aux = Count_Aux+1'b1;
        end
        Count = Count_Aux;
    end
endmodule

高工
2012-12-09 21:11:10     打赏
18楼
帅气的文件头是学anmko的。
蜂鸣器程序是学51FPGA的。
只有这几个汉字是我的。
程序实现了周期性输出两种频率的声音。一个高音一个低音


/*************************************************
* Module Name      : 蜂鸣器实验  
* Engineer          : hanshuyujifen
* Target Device     : EP2C5Q208C8
* Tool versions     : Quartus II 12.0
* Create Date      : 2012-12-09
* Revision          : v1.0
* Description      :   
**************************************************/

module mybeep(sys_clk,sys_rstn,beep);
input sys_clk,sys_rstn;
output beep;

reg beep;
reg [14:0] delay_cnt;
wire [14:0] delay_end;
reg [24:0] div_cnt;

parameter clk_divider0 = 95419;//56817;
parameter clk_divider1 = 12651;//28408;
assign     delay_end = div_cnt[24] ?clk_divider0:clk_divider1;

always @(posedge sys_clk,negedge sys_rstn)
begin
    if(!sys_rstn)
        begin
            div_cnt <=25'b0;
        end
    else
        begin
            div_cnt <= div_cnt +1'b1;
        end
end

always @(posedge sys_clk,negedge sys_rstn)
begin
    if(!sys_rstn)
        begin
            delay_cnt <= delay_end;
        end
    else
        begin
            if(delay_cnt == 15'd0)
                begin
                    beep <= ~beep;
                    delay_cnt <= delay_end;
                end
            else
                begin
                    delay_cnt <= delay_cnt - 1'b1;
                end
        end
end

endmodule

高工
2012-12-09 21:11:37     打赏
19楼
使用状态机实现周期性改变频率

参考书上写法,不知道算不算状态机。
频率那块折腾好久,因为位数设置错了。

/*************************************************
* Module Name      : 蜂鸣器实验,初试状态机  
* Engineer          : hanshuyujifen
* Target Device     : EP2C5Q208C8
* Tool versions     : Quartus II 12.0
* Create Date      : 2012-12-09
* Revision          : v1.0
* Description      :   
**************************************************/

module statebeep(sys_clk,sys_rstn,beep);
input sys_clk,sys_rstn;
output beep;

reg beep;
reg [16:0] delay_cnt;
reg [16:0] delay_end;
reg [26:0] div_cnt;

parameter fre0 = 95419;//状态0
parameter fre1 = 12651;//状态1

reg  state = 0;   //只有两个状态


//assign     delay_end = div_cnt[24] ?clk_divider0:clk_divider1;

//1.5s延时
always @(posedge sys_clk,negedge sys_rstn)
begin
    if(!sys_rstn)
        begin
            div_cnt <=0;
        end
    else
        begin
            if(div_cnt == 27'd75000000)
                div_cnt <= 27'd0;
            else
                div_cnt <= div_cnt +1'b1;
        end
end

//声音频率发生
always @(posedge sys_clk,negedge sys_rstn)
begin
    if(!sys_rstn)
        begin
            delay_cnt <=17'd0;
        end
    else
        begin
            if(delay_cnt == delay_end) 
                delay_cnt <= 17'd0;
            else
                delay_cnt <= delay_cnt +1'b1;
        end
end

//状态转移
always @(posedge sys_clk,negedge sys_rstn)
begin
    if(!sys_rstn)
        begin
            state <= 0;
        end
    else
        if(div_cnt == 27'd75000000)  //延时到,状态转换
            case(state)
                0:   
                    begin
                    state <= 1;
                    delay_end <=    fre0;
                    end
                1:   
                    begin
                    state <= 0;
                    delay_end <=    fre1;
                    end
            endcase
end

always @(posedge sys_clk,negedge sys_rstn)
begin
    if(!sys_rstn)
        begin
            beep <= 1'b1;
        end
    else
        begin
            if(delay_cnt == delay_end)
                beep = ~beep;
            else
                beep <= beep;
        end
end

endmodule

高工
2012-12-11 12:01:41     打赏
20楼
不会用状态机,昨天试了下。程序让人看看,我竟然是参照着两段式状态机写出了一段式的程序。真是随时受不了。
今天,参照着51FPGA提供12864程序,写个三段式状态机。试试,还凑合。
三段式状态机包括状态调转,下一个状态机算,输出逻辑三个always块。
看着并不复杂,以后就这么写了
代码如下:
/*************************************************
* Module Name      : 使用状态机控制蜂鸣器   
* Engineer          : hanshuyujifen
* Target Device     : EP2C5Q208C8
* Tool versions     : QII12
* Create Date      : 2012.12.10
* Revision          : v2.0
* Description      : 使用三段式状态机控制蜂鸣器  
**************************************************/

module statebeep2(sys_clk,sys_rstn,beep);
input sys_clk,sys_rstn;
output beep;

reg [26:0] div_cnt;        //大周期

reg [15:0]    delay_cnt;    //声音周期
reg [16:0] delay_end = 0;
reg [3:0] state = idel;            //状态机
reg [3:0] next_state;
//状态定义
parameter idel = 4'b0000,
             state0 = 4'b0001,
             state1 = 4'b0010,
             state2 = 4'b0100,
             state3 = 4'b1000;

//频率控制
reg beep;
parameter fre0 = 12651;//状态0  1976hz
parameter fre1 = 28408;//状态1  880hz
parameter fre2 = 56817;//状态2  440hz
parameter fre3 = 95419;//状态3  262hz

//状态转换周期
always @(posedge sys_clk,negedge sys_rstn)
begin
    if(!sys_rstn)
        begin
            div_cnt <= 27'b0;
        end
    else
        begin
            if(div_cnt == 27'd50000000)
                div_cnt <=27'd0;
            else
                div_cnt <= div_cnt+1'b1;
        end
end

//状态机转向
always @(posedge sys_clk,negedge sys_rstn)
begin
    if(!sys_rstn)
        begin
            state <= idel;
        end
    else
        begin
            if(div_cnt == 27'd50000000)
                state <= next_state;
        end
end

//状态机逻辑

always@(state)
    begin
        case(state)
            idel        :   
                begin
                    next_state <=state0;
                    delay_end <=fre0;
                end
            state0    :
                begin
                    next_state <= state1;
                    delay_end    <= fre1;
                end
            state1    :
                begin
                    next_state <= state2;
                    delay_end    <= fre2;
                end
            state2    :
                begin
                    next_state <= state3;
                    delay_end    <= fre3;
                end
            state3    :
                begin
                    next_state <= state0;
                    delay_end    <= fre0;
                end
            default     : next_state <= idel;
        endcase
    end
always @(posedge sys_clk,negedge sys_rstn)
begin
    if(!sys_rstn)
        begin
            delay_cnt<= 16'd0;
        end
    else
        begin
            if(delay_cnt == delay_end)
                begin
                    delay_cnt <=0;
                    beep = ~beep;
                end
            else
                delay_cnt <= delay_cnt+1'b1;
        end
end

   
   
endmodule

共40条 2/4 1 2 3 4 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]