通过向FPGA发送指令控制led灯闪烁(Quartus+verilog)

适用于需要周期性控制某些开关的场合(由led灯闪烁显示开闭)

/* plan1 自动模式默认5min开2s,手动模式下9-1s开闭循环指定时长(由指令3 4确定),闭合后每3分钟开2秒指定次数(or时间),之后恢复5min开2s自动模式


module wash(clk,rst_n,rx_data,rx_int,led1,led2,wash_en);

input clk;
input rst_n;
input rx_int;         //触发信号通知接收数据
input [7:0]rx_data;   //接收数据
output reg led1,led2,wash_en;

reg en,en4;
reg rx_int1;
reg rx_int2;
reg [47:0]stop;
reg [47:0]stop1;
reg [47:0]stop2;
reg [47:0]cnt;
reg [47:0]cnt2;
reg [47:0]cnt4;
reg [10:0]state;
reg [10:0]flagcnt;    //手动模式后3min 2s次数
reg  flag;            //手动模式标志位
reg [47:0]value1;
reg [47:0]value10;

parameter s0 = 11'b00000000001;
parameter s1 = 11'b00000000010;
parameter s2 = 11'b00000000100;
parameter s3 = 11'b00000001000;
parameter s4 = 11'b00000010000;
parameter s5 = 11'b00000100000;
parameter s6 = 11'b00001000000;
parameter s7 = 11'b00010000000;
parameter s8 = 11'b00100000000;
parameter s9 = 11'b01000000000;
parameter s10 = 11'b10000000000;

parameter s_9 = 450_000_000;    
parameter s_10 = 500_000_000;  
parameter s_2 = 100_000_000;    
parameter s_180 = 48'd9_000_000_000; //s_180 = 9_000_000_000;
parameter s_300 = 48'd15_000_000_000;//s_300 = 15_000_000_000;
parameter s_1 = 50_000_000;    
parameter s_60 = 3_000_000_000;  

wire rx_int_r;

always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            begin
                rx_int1 <= 0;
                rx_int2 <= 0;
            end
        else
            begin
                rx_int1 <= rx_int;
                rx_int2 <= rx_int1;
            end
    end
    
assign rx_int_r = ~rx_int1 & rx_int2;

always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            begin
                state <= s0;
                stop <= 0;
                stop1 <= 0;
                stop2 <= 0;
            end
        else 
            begin
                if(rx_int_r)
                    begin
                        case(state)
                            s0 : if(rx_data == 8'b00110011)
                                     state <= s1; 
                                  else
                                   begin 
                                    state <= s0;                        
                                    end
                            s1 : if(rx_data == 8'b00110011)
                                    state <= s1;
                                  else if(rx_data == 8'b01000100)
                                    state <= s2;
                                  else
                                    state <= s0;
                            s2 : begin
                                        if(rx_data == 8'b11101000)                        //E8指令进入手动模式
                                            state <= s3;
                                        else if(rx_data == 8'b11100111)           //E7指令手动模式强行停止
                                            state <= s7;
                                        else
                                            state <= s0;
                                  end
                            s3 : begin
                                        stop <= rx_data * s_60;
                                        state <= s4;
                                  end
                            s4 : begin
                                        stop1 <= rx_data * s_1;
                                        state <= s5;
                                  end
                            s5 : begin
                                        stop2 <= stop1 + stop;
                                        state <= s6;      
                                  end
                            s6 : state <= s0;
                            s7 : state <= s0;
                        endcase
                    end
            end
    end

always@ (posedge clk or negedge rst_n) 
if( ! rst_n ) begin  en <= 0; flag <= 0; cnt2<= 0;flagcnt<= 0;value1<= s_2;value10<= s_300;wash_en <= 0;end
else if (state == s6 ) begin en <= 1; flagcnt<= 0; value1<= s_9;value10<= s_10;end
else if (en == 1 )
      begin   
        if (cnt2 ==  stop2 || state == s7) 
            begin 
               en <= 0; 
                wash_en <= 1;
                flag<= 1;
                value1<= s_2;
                value10<= s_180;  
             end
        else cnt2 <= cnt2 + 1'b1; 
     end
else if (flag == 1 && cnt ==  s_180)
      begin   
        if (flagcnt >=  2 )  begin flag<= 0;value10<= s_300; end //if (flagcnt ==  160 )
        else flagcnt <= flagcnt + 1'b1; 
     end
else begin cnt2 <= 0; wash_en <= 0;end

always@ (posedge clk or negedge rst_n) 
if( ! rst_n) begin cnt<= 33 'd0; end 
else if( cnt2==1) cnt<= 33 'd0; 
else
        begin
        if (cnt >=  value10 ) cnt <= 36 'd0; 
        else cnt <= cnt + 1'b1;
        end


always@ (posedge clk or negedge rst_n) 
if( ! rst_n) led1<= 0 ;
else
   begin
        if (cnt >=1 &&  cnt <=value1 ) led1 <= 1; 
        else led1 <= 0;
    end
    
always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n )
            begin
                led2 <= 0;
                cnt4 <= 0;
            end
        else if(state == s6)
            begin
                led2 <= 1;
                cnt4 <= 0;
            end
        else if(led2)
            begin
                if(cnt4 == stop|| state == s7)
                    begin
                        led2 <= 0;
                        cnt4 <= 0;
                    end
                else
                    cnt4 <= cnt4 + 1'b1;
            end
    end
            
endmodule*/


// plan2 自动模式默认5min开2s n次,之后7min开2s n次,之后之后10min开2s 无限次,手动模式下9-1s开闭循环指定时长(由指令3 4确定)
module wash(clk,rst_n,rx_data,rx_int,led1,led2,wash_en);

input clk;
input rst_n;
input rx_int;
input [7:0]rx_data;
output reg led1;
output reg led2;
output reg wash_en;

reg en,en0,en1,en2;
reg rx_int1;
reg rx_int2;

reg [47:0]stop;
reg [47:0]stop1;
reg [47:0]stop2;

reg [47:0]cnt,cnt2,cnt4;
reg [10:0]state;
reg [10:0]count0,count1,count2;

reg [47:0]value1;     //占空比高电平
reg [47:0]value10;   //占空比总时长

parameter s0 = 11'b00000000001;
parameter s1 = 11'b00000000010;
parameter s2 = 11'b00000000100;
parameter s3 = 11'b00000001000;
parameter s4 = 11'b00000010000;
parameter s5 = 11'b00000100000;
parameter s6 = 11'b00001000000;
parameter s7 = 11'b00010000000;
parameter s8 = 11'b00100000000;
parameter s9 = 11'b01000000000;
parameter s10 = 11'b10000000000;

/*
parameter s_9 = 9*1_000_0/20;    //9*1_000_0/20;用于仿真
parameter s_10 = 10*1_000_0/20;  //10*1_000_0/20;
parameter s_2 = 2*1_000_0/20;    //2*1_000_0/20;
parameter s_300 = 300*1_000_0/20;//300*1_000_0/20;
parameter s_420 = 420*1_000_0/20;//300*1_000_0/20;
parameter s_600 = 600*1_000_0/20;//300*1_000_0/20;
parameter s_1 = 1*1_000_0/20;    //1*1_000_0/20;
parameter s_60 = 60*1_000_0/20;  //60*1_000_0/20;
*/

parameter s_9 = 450_000_000;       //9秒次数= 9*1_000_000_000/20; 20ns为时钟周期
parameter s_10 = 500_000_000;  
parameter s_2 = 100_000_000;    
parameter s_300 = 48'd15_000_000_0;//s_300 = 15_000_000_000;
parameter s_420 = 48'd21_000_000_0;//s_420 = 21_000_000_000;
parameter s_600 = 48'd30_000_000_0;//s_600 = 30_000_000_000;
parameter s_1 = 50_000_000;    
parameter s_60 = 3_000_000_000;

parameter s_180 = 48'd9_000_000_00; //s_180 = 9_000_000_000;

wire rx_int_r;

always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            begin
                rx_int1 <= 0;
                rx_int2 <= 0;
            end
        else
            begin
                rx_int1 <= rx_int;
                rx_int2 <= rx_int1;
            end
    end
    
assign rx_int_r = ~rx_int1 & rx_int2;      //检测下降沿

always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            begin
                state <= s0;
                stop <= 0;
                stop1 <= 0;
            stop2 <= 0;
            end
        else 
            begin
                if(rx_int_r)
                    begin
                        case(state)
                            s0 : if(rx_data == 8'b00110011)
                                    state <= s1;
                                  else
                                   begin 
                                    state <= s0;                        
                                    end
                            s1 : if(rx_data == 8'b00110011)
                                    state <= s1;
                                  else if(rx_data == 8'b01000100)
                                    state <= s2;
                                  else
                                    state <= s0;
                            s2 : begin
                                        if(rx_data == 8'b11101000)                        //E8指令进入手动模式
                                            state <= s3;
                                        else if(rx_data == 8'b11100111)           //E7指令手动模式强行停止
                                            state <= s7;
                                        else
                                            state <= s0;
                                  end
                            s3 : begin
                                        stop <= rx_data * s_60;
                                        state <= s4;
                                  end
                            s4 : begin
                                        stop1 <= rx_data * s_1;
                                        state <= s5;
                                  end
                            s5 : begin
                                        stop2 <= stop1 + stop;
                                        state <= s6;      
                                  end
                            s6 : state <= s0;
                            s7 : state <= s0;
                        endcase
                    end
            end
    end

    
always@ (posedge clk or negedge rst_n) 
if( ! rst_n ) begin  en <= 0; en0 <= 1;en1 <= 0;en2 <= 0; cnt2<= 0;count0 <= 0;count1 <= 0;value1<= s_2;value10<= s_300;wash_en <= 0;end
else if (state == s6 ) begin en <= 1; cnt2 <= 0;value1<= s_9;value10<= s_10;end
else if (en == 1 )
      begin   
        if (cnt2 ==  stop2 || state == s7) 
            begin 
               en <= 0; 
                cnt2 <= 0;
                wash_en <= 1;
                value1<= s_2;
                if(en0) value10<= s_300; 
                else if(en1) value10<= s_420; 
                else value10<= s_600; 
             end
        else cnt2 <= cnt2 + 1'b1; 
     end
else if (en0 == 1 && cnt >=  s_300)    
      begin  
        if (count0 >=  2 )  begin en0<= 0;en1<= 1;value10<= s_420; end 
        else count0 <= count0 + 1'b1; 
     end
else if (en1 == 1 && cnt >=  s_420)    
      begin  
        if (count1 >=  2 )  begin en1<= 0;en2<= 1;value10<= s_600; end 
        else count1 <= count1 + 1'b1; 
     end
else begin wash_en <= 0;end

always@ (posedge clk or negedge rst_n) 
if( ! rst_n) begin cnt<= 48 'd0; end 
else if( cnt2==1) cnt<= 48 'd0; 
else
        begin
        if (cnt >=  value10 ) cnt <= 0; 
        else cnt <= cnt + 1'b1;
        end


always@ (posedge clk or negedge rst_n) 
if( ! rst_n) led1<= 0 ;
else
   begin
        if (cnt >=1 &&  cnt <=value1 ) led1 <= 1; 
        else led1 <= 0;
    end

always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n )
            begin
                led2 <= 0;
                cnt4 <= 0;
            end
        else if(state == s6)
            begin
                led2 <= 1;
                cnt4 <= 0;
            end
        else if(led2)
            begin
                if(cnt4 == stop|| state == s7)
                    begin
                        led2 <= 0;
                        cnt4 <= 0;
                    end
                else
                    cnt4 <= cnt4 + 1'b1;
            end
    end
                
endmodule

下图为自动模式led1的示波器波形图(3-4-6s代替5-7-10m = 300-420-600s,2s不变,次数由8-16h = 96-137-无限次 压缩为3-3-无限次,可根据实际需求调整)

 下图为手动模式led1+led2的示波器波形图(1m+2s代替5m+5s)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验目的: 通过 FPGA 实现按键控制 LED 的亮灭,加深对 FPGA 的理解和应用。 实验器材: - FPGA 开发板(例如 DE10-Lite) - USB 线 - 按键模块 - LED 模块 实验步骤: 1. 搭建硬件电路 将按键模块和 LED 模块插入 FPGA 开发板的相应引脚上,并将 FPGA 开发板与电脑连接。 按键模块连接方式: - K1 和 K2 分别连接到 FPGA 引脚的 PIN_23 和 PIN_25 上。 - GND 连接到 FPGA 引脚的 PIN_19 上。 LED 模块连接方式: - VCC 连接到 FPGA 引脚的 PIN_3 上。 - GND 连接到 FPGA 引脚的 PIN_1 上。 - LED1 和 LED2 分别连接到 FPGA 引脚的 PIN_10 和 PIN_12 上。 2. 新建 Quartus 工程 打开 Quartus 软件,选择 File -> New Project Wizard,新建一个工程。 3. 添加 Verilog 文件 在工程目录下新建一个 Verilog 文件,将以下代码复制进去: ```verilog module key_led( input clk, input k1, input k2, output led1, output led2 ); reg [1:0] state; always @(posedge clk) begin case(state) 2'b00: begin led1 <= 1'b0; led2 <= 1'b0; if(k1) state <= 2'b01; if(k2) state <= 2'b10; end 2'b01: begin led1 <= 1'b1; led2 <= 1'b0; if(!k1) state <= 2'b00; end 2'b10: begin led1 <= 1'b0; led2 <= 1'b1; if(!k2) state <= 2'b00; end default: state <= 2'b00; endcase end endmodule ``` 这段 Verilog 代码实现了按键控制 LED 的功能,在上升沿时检测按键的状态,根据按键的状态控制 LED 的亮灭。 4. 设计约束文件 在工程目录下新建一个 SDC 文件,将以下代码复制进去: ```tcl create_clock -name clk -period 10.0 -waveform {0 5.0} [get_ports clk] set_input_delay -clock clk -max 2.0 [get_ports k1] set_input_delay -clock clk -max 2.0 [get_ports k2] set_output_delay -clock clk -max 2.0 [get_ports led1] set_output_delay -clock clk -max 2.0 [get_ports led2] ``` 这段 SDC 代码定义了时钟和输入输出的时序约束。 5. 编译工程 在 Quartus 软件中,选择 Processing -> Start Compilation,编译工程。 6. 下载到 FPGA 开发板 编译成功后,在 Quartus 软件中选择 Tools -> Programmer,将编译好的文件下载到 FPGA 开发板。 7. 运行实验 将 FPGA 开发板接通电源,按下 K1 按键,LED1 亮起;按下 K2 按键,LED2 亮起。松开按键后,LED 熄灭。 实验效果: 通过按键控制 LED 的亮灭,实现了简单的数字逻辑电路的设计和实现。 实验总结: 本实验通过 FPGA 实现按键控制 LED 的亮灭,加深了对 FPGA 的理解和应用。在设计数字逻辑电路时,需要注意时序约束的设置,确保电路能够正常工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值