• 基于FPGA的售货机


    一、要求

    1. 默认只接收0.5元、1元投币。
    2. 货物为2.5元。
    3. 满足2.5元后自动出货,出货动作用4个LED同时闪烁(闪烁2s)表示。
    4. 满足3元之后,自动出货并找零,动作用4个LED做流水灯表示(同样闪烁2s)。

    二、效果

    1. 默认只接收0.5元、1元投币。
    2. 货物有4种可以选择,价格分别为0.5,1.5,2.4,3元。
    3. 满足当前选择的商品价格后自动出货,自动出货并找零,出货动作用4个LED做跑马灯(持续2s)表示。
    4. 显示当前投币的总额、当前选择的商品的价格以及找零的数目。
    5. 复位时播放音乐并显示彩灯。
    6. 投币不足目标价格时可以取消,动作用灯闪烁表示(2s)。

    三、设计思路

    1.按键

    在这里插入图片描述

    2.数码管

    数码管6位,从左往右,依次是两位的投币输入金额,两位的商品价格
    以及两位的找零金额。初始显示1位,两位,1位。
    位选总共六种显示状态,段选10种状态。

    3.LED

    在这里插入图片描述

    4.蜂鸣器

    在这里插入图片描述

    四、程序流程图

    在这里插入图片描述

    五、项目RTL视图

    在这里插入图片描述

    六、代码实现

    1.按键消抖

    module key_drive (
        input   wire clk,
        input   wire rst_n,
        input   wire [2:0] key, //按键
        output  reg [19:0] value //输出到数码管显示的值
    );
    
    parameter MAX_VALUE = 20'd1024;     //最大显示数字
    
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            value <= 20'd0;
        end
    
        else if (value >= MAX_VALUE) begin
            value <= 20'd0;
        end
    
        // 根据按下的键进行对应的操作
        else begin
            if(key[0]) begin
                value <= 2;
            end
            else if (key[1]) begin
                value <= 3;
            end
            else if (key[2]) begin
                value <= 4;
            end
            else begin
                value <= value;
            end
        end
    end
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    2.售货机

    module machine_drive(
    	input    wire			   clk			,        //时钟信号
    	input    wire			   rst_n		   ,			//复位信号
    	input    wire	[2:0] 	key			,        //3个按键 KEY4-key[2]:1元 KEY3-key[1]:0.5元 KEY2-key[0]:更换商品价格
    	
    	output	reg 	[3:0] 	led_value	,			//对应led显示效果的类型
    	output 	reg 	[6:0] 	price_put	,			//用户投入的钱
    	output 	reg 	[6:0] 	price_need	,			//商品价格
    	output 	reg 	[6:0] 	price_out				//找零
    );
    
    
    
    //四种商品对应价格
    parameter	P1 = 7'd5;
    parameter	P2 = 7'd15;
    parameter	P3 = 7'd24;
    parameter	P4 = 7'd30;
    
    parameter MAX_TIME = 28'd100_000_000;	//退款过程持续时间
    
    reg 	[1 :0] 	price_tmp			  	;	//当前商品价格
    reg 	[27:0] 	cnt_time 			 	;   //用作退款过程计时
    reg 			flag_can_operation  	;	//可以继续投币和切换商品
    reg 			flag_is_retreat_end 	;	//结算完毕
    
    
    wire			flag_is_retreat     	;	//开始结算
    wire			flag_price_is_enough	;	//可以买下商品
    reg		[6:0] 	price_put_last      	;	//结算前的投币数
    
    
    	
    //结算倒计时模块
    always @(posedge clk,negedge rst_n) begin
    	if(!rst_n)begin
    		cnt_time <= 28'd0;          //初始设置计数器为0
    		flag_can_operation <= 1'b1 ;//设置KEY键可操作
    		flag_is_retreat_end <= 1'b0;//设置结算完毕标志为0
    	end
    	else begin
    		if (flag_is_retreat) begin     //开始结算
    			cnt_time <= MAX_TIME;       //计数器设置最大值
    			flag_can_operation <= 1'b0 ;//当前处于结算状态,设置KEY键不可用
    			flag_is_retreat_end <= 1'b0;//设置结算未完毕
    		end
    		else if(cnt_time > 28'd1) begin //计数器数值大于1
    			cnt_time <= cnt_time - 28'd1;//倒计时
    			flag_can_operation <= 1'b0;  //当前处于结算状态,设置KEY键不可操作
    			flag_is_retreat_end <= 1'b0; //设置结算未完毕
    		end
    
    		else if(cnt_time == 28'd1) begin//计数器倒计时数到1
    			cnt_time <= 28'd0;           //计数器清零
    			flag_can_operation <= 1'b1;  //结算完毕,设置KEY键可操作
    			flag_is_retreat_end <= 1'b1; //设置结算完毕
    		end
    		else begin
    			cnt_time <= cnt_time;
    			flag_can_operation <= flag_can_operation;
    			flag_is_retreat_end <= 1'b0;
    		end
    			
    	end
    	 
    end
    
    //按下KEY2-key[0]切换商品价格 
    always@(posedge clk,negedge rst_n)begin
    	if(!rst_n)begin
    		price_tmp<= 2'd0;  //初始设置商品价格为1号商品
    	end
    	else if(flag_can_operation) begin//当前按键可操作
    		// 当没有投币的时候按下 KEY2-key[0] 为切换商品 
    		if(key[0] && ! price_put) begin
    			price_tmp <= (price_tmp + 2'd1) % 4;//%操作,循环切换
    		end
    		else begin
    			price_tmp <= price_tmp;	//没有按下切换按键,当前商品价格保持
    		end
    	end
    
    	else begin
    		price_tmp <= price_tmp;	
    	end 
    end
    
    // 切换商品价格
    always@(posedge clk,negedge rst_n)begin
    	if(!rst_n)
    		price_need<=P1;
    	else
    		case(price_tmp)
    			2'b00 : price_need <= P1;
    			2'b01 : price_need <= P2;
    			2'b10 : price_need <= P3;
    			2'b11 : price_need <= P4;
    			default:price_need <= P1;
    		endcase
    end
    
    //切换商品价格时led灯光效果
    always @(posedge clk,negedge rst_n) begin
    	if(!rst_n)
    		led_value <= 4'd1;
    	//退款的时候判断是 补差价 或者 全额退款
    	//补差价为流水灯效果
    	//全额退款为闪烁效果	
    	else if(flag_is_retreat)begin//开始结算
    		led_value <= price_put_last >= price_need ? 4'd6 : 4'd7 ;//当前投币数大于等于商品价格,LED状态为6,否则状态为7
    	end
    
    	//正常操作状态根据当前选择商品亮起对应商品led
    	else if(flag_can_operation)begin
    		case(price_tmp)
    			2'b00 : led_value <= 4'd2;
    			2'b01 : led_value <= 4'd3;
    			2'b10 : led_value <= 4'd4;
    			2'b11 : led_value <= 4'd5;
    			default:led_value <= 4'd2;
    		endcase
    	end
    	
    	else 
    		led_value <= led_value;
    end
    
    //用户通过按键进行投币
    always@(posedge clk,negedge rst_n)begin
    	if(!rst_n)begin
    		price_put_last<=7'd0;//累计投币数初始化为0
    	end
    	else if(flag_can_operation) begin//当前按键可操作
    		//超过100 或者 
    		if(price_put_last>=7'd100 || flag_is_retreat) begin//当前投币大于10超过可显示数字或开始结算,投币清零
    			price_put_last<=7'd0;
    		end
    		/*
    			按下 key[2] 投币 + 10
    			按下 key[1] 投币 + 5
    		*/	
    		else begin
    			if(key[2])//KEY4-key[2]投币1元
    				price_put_last<=price_put_last+7'd10;
    			else if(key[1])//KEY3-key[1]投币0.5元
    				price_put_last<=price_put_last+7'd5;
    			else	
    				price_put_last<=price_put_last;
    		end
    	end
    	else begin
    		price_put<=price_put;
    	end
    end
    
    //投币数码显示保持2s
    always @(posedge clk,negedge rst_n) begin
    	if(!rst_n)begin
    		price_put<=7'd0;
    	end
    
    	else if(!flag_can_operation)//按键不可操作
    		price_put <= price_put;//输出投币保持
    
    	else 
    		price_put <= price_put_last;//否则将当前投币值赋值给输出投币寄存器
    end
    
    // 输出找零
    always @(posedge clk,negedge rst_n) begin
    	if(!rst_n)begin
    		price_out <= 7'd0;//初始找零0元
    	end
    	//结算完毕,归零
    	else if(flag_is_retreat_end) begin
    	 	price_out =7'd0 ;
    	end	
    	//当退款标志到来,计算退款金额为 补差价 或者 全额退款
    	else if(flag_is_retreat) begin//开始结算
    		price_out <= price_put_last >= price_need ? price_put_last - price_need : price_put_last ;//当前投币大于商品价格则找零差值,否则找零为0
    	end
    
    	else begin
    		price_out <= price_out;
    	end
    end
    
    //当投币可以买下商品
    assign flag_price_is_enough = price_put_last >= price_need;//当前投币数大于等于商品价格,投币足够标志置1
    //为了保证在结算前得到最后一次投币数量
    // assign price_put_last = price_put;
    // 当币足够 或者 在投币过程选择切换商品则开始退款
    assign flag_is_retreat = flag_price_is_enough || (price_put && key[0]);//投币足够或退款,结算处理标志置1
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195

    3.LED

    module led_drive (
        input   wire          clk  ,//时钟信号
        input   wire          rst_n,//复位信号
        input   wire    [3:0] value,//LED显示状态
    
        output  reg     [3:0] led   //4个LED输出
    );
    /*
        value       效果
    
        0           全灭
        1           全亮
        2           只亮led[0]
        3           只亮led[1]
        4           只亮led[2]
        5           只亮led[3]
        6           流水灯
        7           闪烁
    */
    parameter MAX_TIME_RUNNING = 28'd4_000_000;     //流水灯频率0.08s
    parameter MAX_TIME_FLASH =  28'd10_000_000;     //闪烁频率0.2s
    
    
    reg [27:0] cnt_time_running ;       //流水灯计时器
    reg [27:0] cnt_time_flash;          //闪烁灯计时器
    
    reg [7:0] led_running;              //流水灯状态寄存器
    reg [3:0] led_flash;                //闪烁灯状态寄存器
    
    //流水灯计数器0.08s
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            cnt_time_running <=28'd1;
        else if(value == 4'd6) begin
            if(cnt_time_running == MAX_TIME_RUNNING)
                cnt_time_running <=28'd1;
            else
                cnt_time_running <= cnt_time_running+28'd1;
        end
        else 
            cnt_time_running <= 28'd1;
    end
    
    //闪烁灯计数器0.2s
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            cnt_time_flash <=28'd1;
        else if (value == 4'd7) begin
            if(cnt_time_flash == MAX_TIME_FLASH )
                cnt_time_flash <=28'd1;
            else
                cnt_time_flash <= cnt_time_flash+28'd1;
        end
        else 
            cnt_time_flash <= 28'd1;
    end
    
    //流水灯状态切换 间隔0.08s
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            led_running <= 8'b00001111;
        else if(cnt_time_running == MAX_TIME_RUNNING)begin
            led_running <= {led_running[0],led_running[7:1]};
        end
        else 
            led_running <=led_running;
    	
    end
    
    //闪烁状态切换 间隔0.2s
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            led_flash <= 4'b0000;
        else if(cnt_time_flash == MAX_TIME_FLASH)begin
            led_flash <= ~led_flash;
        end
        else 
            led_flash <=led_flash;
    	
    end
    
    //根据value值输出对应灯效果
    always @(*) begin
        case(value)
            4'd0: begin
                led = 4'b0000;//默认状态LED全灭
            end
    
            4'd1:begin
                led = 4'b1111;//
            end
    
            4'd2:begin
                led = 4'b0001;//选择第一种商品
            end
    
            4'd3:begin
                led = 4'b0010;//选择第二种商品
            end
    
            4'd4:begin
                led = 4'b0100;//选择第三种商品
            end
    
            4'd5:begin
                led = 4'b1000;//选择第四种商品
            end
    
            4'd6: begin
    		      led = led_running[3:0];//购买成功找零不找零,流水灯
            end
    
            4'd7:begin
                led = led_flash;//取消订单,闪烁
            end
            default : led = 4'b0000;
        endcase
    end
    endmodule 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119

    4.数码管

    位选

    module sel_drive(
    	input    wire             clk			   ,
    	input    wire             rst_n			,
    	input    wire    [6:0]    price_put		,	//投入的钱
    	input    wire    [6:0]    price_need	,	//商品的价格
    	input    wire    [6:0]    price_out		,	//找零的钱
    
    	output    reg    [5:0]    sel				//数码管位选
    );
    //状态
    localparam state0 = 3'd0;
    localparam state1 = 3'd1;
    localparam state2 = 3'd2;
    localparam state3 = 3'd3;
    localparam state4 = 3'd4;
    localparam state5 = 3'd5;
    
    parameter	 MAX_NUM = 1_000;//计数器最大计数值 刷新频率20微秒
    
    reg    [2 :0]    current_state;
    reg    [2 :0]    next_state;
    reg    [20:0]	  cnt; //时钟分频计数器
    reg              flag;
    
    //计数器
    always @(posedge clk or negedge rst_n)begin
    	if(!rst_n)begin
    		flag <= 1'b0;
    		cnt <= 0;
    	end
    	else if(cnt == 0)begin//一轮计数完毕
    		flag <= 1'b1;
    		cnt <= 1;
    	end
    	else	begin 
    		flag <= 1'b0;
    		cnt <= (cnt + 1'b1) % MAX_NUM;//循环+1
    	end
    end
    // 状态跳转
    always @(posedge clk or negedge rst_n) begin
    	if(!rst_n) begin
    		current_state <= state0;
    	end
    	
    	else if(flag) begin
    		current_state <= next_state;
    	end
    	
    	else 
    		current_state <= current_state;
    end
    
    
    //状态判断
    always @(*) begin
    	if(!rst_n) begin
    		next_state <= state0;
    	end
    	
    	else if(flag) begin
    		case(current_state)
    			state0: begin
    				next_state <= state1;
    			end
    			state1: begin
    				next_state <= state2;
    			end
    			state2: begin
    				next_state <= state3;
    			end
    			state3: begin
    				next_state <= state4;
    			end
    			state4: begin
    				next_state <= state5;
    			end
    			state5: begin
    				next_state <= state0;
    			end
    			
    			default:begin
    				next_state <= state0;
    			end
    		endcase
    	end
    	
    	else begin
    		next_state <= next_state;
    	end
    end
    
    
    //根据value的值确定需要亮几位
    always@(current_state) begin
    	case (current_state)
    		state0: begin                 //右第一位数码管显示
    			sel <= 6'b011111;
    		end
    		state1: begin                 //右第二位数码管显示
    			if (price_out >=1) begin
    				sel <= 6'b101111;
    			end
    			else begin
    				sel <= 6'b111111;
    			end
    		end
    		state2: begin                 //右第三位数码管显示
    			if (price_need >=0) begin
    				sel <= 6'b110111;
    			end
    			else begin
    				sel <= 6'b111111;
    			end
    		end
    		state3: begin                 //右第四位数码管显示
    			if (price_need >=1) begin
    				sel <= 6'b111011;
    			end
    			else begin
    				sel <= 6'b111111;
    			end
    		end
    		state4: begin                 //右第五位数码管显示
    			if (price_put >=0) begin
    				sel <= 6'b111101;
    			end
    			else begin
    				sel <= 6'b111111;
    			end
    		end
    		state5: begin                 //右第五位数码管显示
    			if (price_put >=1) begin
    				sel <= 6'b111110;
    			end
    			else begin
    				sel <= 6'b111111;
    			end
    		end
    		default:begin
    			sel <= 6'b111111;
    		end
    	endcase
    end
    endmodule 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145

    段选

    module seg_drive(
        input   wire    			 clk         ,
        input   wire    			 rst_n       ,       //复位
        input   wire    [5:0]   sel         ,       //数码管位选
        input   wire    [6:0]   price_put   ,       //投入的钱
        input   wire    [6:0]   price_need  ,       //商品的价格
        input   wire    [6:0]   price_out   ,       //找零的钱
        output   reg    [7:0]   seg                 //数码管段选
       
    );
    
    reg [3:0] num;
    always@(*) begin
        case(sel)
            //投入的钱
    		6'b111_110: num = (price_put % 100) / 10;       //十位  
    		6'b111_101: num = price_put % 10;               //个位
            //需要的钱
    		6'b111_011: num = (price_need % 100) / 10;      //十位
    		6'b110_111: num = price_need % 10;              //个位
            //找回的钱
    		6'b101_111: num = (price_out % 100) / 10;       //十位
    		6'b011_111: num = price_out % 10;               //个位
    		default:num = 4'd0;
       endcase
    end
    
    always @ (*) begin
        //需要显示小数点
        if(!sel[1] || !sel[3] || !sel[5]) begin
            case(num)
                4'd0:    seg = 8'b1100_0000; //匹配到后参考共阳极真值表
                4'd1:    seg = 8'b1111_1001;
                4'd2:    seg = 8'b1010_0100;
                4'd3:    seg = 8'b1011_0000;
                4'd4:    seg = 8'b1001_1001;
                4'd5:    seg = 8'b1001_0010;
                4'd6:    seg = 8'b1000_0010;
                4'd7:    seg = 8'b1111_1000;
                4'd8:    seg = 8'b1000_0000;
                4'd9:    seg = 8'b1001_0000;
                default : seg = 8'b1100_0000;
            endcase
        end
           
        else begin
            case(num)
                4'd0:    seg = 8'b0100_0000; //匹配到后参考共阳极真值表
                4'd1:    seg = 8'b0111_1001;
                4'd2:    seg = 8'b0010_0100;
                4'd3:    seg = 8'b0011_0000;
                4'd4:    seg = 8'b0001_1001;
                4'd5:    seg = 8'b0001_0010;
                4'd6:    seg = 8'b0000_0010;
                4'd7:    seg = 8'b0111_1000;
                4'd8:    seg = 8'b0000_0000;
                4'd9:    seg = 8'b0001_0000;
                default : seg = 8'b0100_0000;
            endcase
        end
    
    end
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    5.音乐播放

    module freq_select
    (
    	input   wire 		clk,
    	input   wire		rst_n,
    		
    	output  reg 		status, //蜂鸣器1/0
    	output  reg [2:0]	spec_flag//音符
    
    );
    
    parameter NOTE_NUM=6'd50;  //50个音符
    //中
    parameter   DO  	= 20'd95600		;//1
    parameter   RE  	= 20'd83150		;//2
    parameter   MI  	= 20'd75850		;//3
    parameter   FA  	= 20'd71600		;//4
    parameter   SO  	= 20'd63750		;//5
    parameter   LA    = 20'd56800		;//6
    parameter   XI    = 20'd50600		;//7
    //高
    parameter   HDO  	= 16'd47750		;//1
    parameter   HRE  	= 16'd42250		;//2
    parameter   HMI  	= 16'd37900		;//3
    parameter   HFA  	= 16'd37550		;//4
    parameter   HSO  	= 16'd31850		;//5
    parameter   HLA   = 16'd28400		;//6
    parameter   HXI   = 16'd25400		;//7
    //低
    parameter   LDO  	= 20'd190800	;//1
    parameter   LRE  	= 20'd170050	;//2
    parameter   LMI  	= 20'd151500	;//3
    parameter   LFA  	= 20'd143250	;//4
    parameter   LSO  	= 20'd127550	;//5
    parameter   LLA    = 20'd113600	;//6
    parameter   LXI    = 20'd101200	;//7
    
    
    reg [25:0] 	inte_cnt;  		//300ms,间隔
    reg [19:0] 	note_cnt;		//音符持续时间计时
    reg [5:0] 	spec_cnt;		//音谱个数计数
    reg [19:0] 	spec_data;		//音符频率
    reg [25:0] 	continue_time;	//持续时间
    reg [27:0] 	blank_time; 		//空白时间 
    
    wire[18:0] 	duty_data;		//占空比数据
    wire 			end_note; 		//音符结束时间
    wire 			end_spectrum;	//音谱结束时间
    
    //音符之间间隔时间计数
    always@(posedge clk,negedge rst_n)begin
    	if(!rst_n)
    		inte_cnt<=26'b0;
    	else if(inte_cnt==continue_time+blank_time)
    		inte_cnt<=26'b0;
    	else begin
    		inte_cnt<=inte_cnt+1'b1;
    	end
    end
    
    //单个音符频率计数
    always@(posedge clk or negedge rst_n)begin
    	if(!rst_n)begin
    		note_cnt <= 20'd0;//20
    	end 
    	else if(end_note)begin
    		note_cnt <= 20'd0;
    	end 
    	else begin
    		note_cnt <= note_cnt + 1'd1;
    	end 
    end
    
    //音符数计时
    always@(posedge clk or negedge rst_n)begin
    	if(!rst_n)begin
    		spec_cnt <= 6'd0;
    	end 
    	else if(end_spectrum)begin
    		spec_cnt <= 6'd0;
    	end 
    	else if(inte_cnt == continue_time+blank_time)begin
    		spec_cnt <= spec_cnt + 1'd1;
    	end 
    	else begin
    		spec_cnt <= spec_cnt;
    	end 
    end 
    
    always@(posedge clk or negedge rst_n)begin
    	case(spec_cnt)
    			6'd0:	continue_time<=26'd10_000_000;//你爱我
    			6'd1:	continue_time<=26'd_000_000;
    			6'd2:	continue_time<=26'd10_000_000;						
    			6'd3:	continue_time<=26'd20_000_000;
    		
    			6'd4:	continue_time<=26'd10_000_000;//我爱你蜜雪					
    			6'd5:	continue_time<=26'd10_000_000;					
    			6'd6:	continue_time<=26'd20_000_000;					
    			6'd7:	continue_time<=26'd10_000_000;
    			6'd8:	continue_time<=26'd10_000_000;
    			
    			6'd9:	continue_time<=26'd10_000_000;//冰城甜蜜				
    			6'd10:continue_time<=26'd15_000_000;
    			6'd11:continue_time<=26'd10_000_000;
    			6'd12:continue_time<=26'd9_000_000;
    			
    			6'd13:continue_time<=26'd25_000_000;//蜜
    			
    			6'd14:continue_time<=26'd10_000_000;//你爱我
    			6'd15:continue_time<=26'd10_000_000;
    			6'd16:continue_time<=26'd10_000_000;
    			6'd17:continue_time<=26'd20_000_000;
    			
    			6'd18:continue_time<=26'd10_000_000;//我爱你蜜雪
    			6'd19:continue_time<=26'd10_000_000;
    			6'd20:continue_time<=26'd20_000_000;
    			6'd21:continue_time<=26'd10_000_000;
    			6'd22:continue_time<=26'd10_000_000;
    
    			6'd23:continue_time<=26'd10_000_000;//冰城甜蜜
    			6'd24:continue_time<=26'd15_000_000;
    			6'd25:continue_time<=26'd10_000_000;
    			6'd26:continue_time<=26'd9_000_000;
    
    			6'd27:continue_time<=26'd25_000_000;//蜜
    			
    			6'd28:continue_time<=26'd20_000_000;//你爱
    			6'd29:continue_time<=26'd20_000_000;
    
    			6'd30:continue_time<=26'd20_000_000;//我呀
    			6'd31:continue_time<=26'd10_000_000;
    			6'd32:continue_time<=26'd10_000_000;
    			
    			6'd33:continue_time<=26'd20_000_000;//我爱
    			6'd34:continue_time<=26'd10_000_000;
    			6'd35:continue_time<=26'd10_000_000;
    
    			6'd36:continue_time<=26'd50_000_000;//你
    			
    		   6'd37:continue_time<=26'd10_000_000;//你爱我
    			6'd38:continue_time<=26'd10_000_000;
    			6'd39:continue_time<=26'd10_000_000;						
    			6'd40:continue_time<=26'd20_000_000;
    		
    			6'd41:continue_time<=26'd10_000_000;//我爱你蜜雪					
    			6'd42:continue_time<=26'd10_000_000;					
    			6'd43:continue_time<=26'd20_000_000;					
    			6'd44:continue_time<=26'd10_000_000;
    			6'd45:continue_time<=26'd10_000_000;
    			
    			6'd46:continue_time<=26'd10_000_000;//冰城甜蜜				
    			6'd47:continue_time<=26'd25_000_000;
    			6'd48:continue_time<=26'd10_000_000;
    			6'd49:continue_time<=26'd9_000_000;
    			
    			6'd50:continue_time<=26'd25_000_000;//蜜
    			default:	continue_time<=26'd24_000_000;
    		endcase
    end
    //空白时间
    always@(spec_cnt)begin
    	case(spec_cnt)
    			6'd0:	blank_time<=26'd2_000_000;//你爱我
    			6'd1:	blank_time<=26'd2_000_000;
    			6'd2:	blank_time<=26'd2_000_000;						
    			6'd3:	blank_time<=26'd5_000_000;
    	
    			6'd4:	blank_time<=26'd2_000_000;	//我爱你蜜雪					
    			6'd5:	blank_time<=26'd2_000_000;					
    			6'd6:	blank_time<=26'd5_000_000;					
    			6'd7:	blank_time<=26'd2_000_000;
    			6'd8:	blank_time<=26'd2_000_000;	
    			
    			6'd9:	blank_time<=26'd2_000_000;	//冰城甜蜜					
    			6'd10:blank_time<=26'd5_000_000;
    			6'd11:blank_time<=26'd2_000_000;
    			6'd12:blank_time<=26'd2_000_000;
    			
    			6'd13:blank_time<=26'd5_000_000;//蜜
    			
    			6'd14:blank_time<=26'd2_000_000;//你爱我
    			6'd15:blank_time<=26'd2_000_000;
    			6'd16:blank_time<=26'd2_000_000;
    			6'd17:blank_time<=26'd2_000_000;
    			
    			6'd18:blank_time<=26'd2_000_000;//我爱你蜜雪
    			6'd19:blank_time<=26'd2_000_000;
    			6'd20:blank_time<=26'd5_000_000;
    			6'd21:blank_time<=26'd2_000_000;
    			6'd22:blank_time<=26'd2_000_000;
    		
    			6'd23:blank_time<=26'd2_000_000;//冰城甜蜜
    			6'd24:blank_time<=26'd5_000_000;
    			6'd25:blank_time<=26'd2_000_000;
    			6'd26:blank_time<=26'd2_000_000;
    
    			6'd27:blank_time<=26'd5_000_000;//蜜
    			
    			6'd28:blank_time<=26'd2_000_000;//你爱
    			6'd29:blank_time<=26'd5_000_000;
    			
    			6'd30:blank_time<=26'd2_000_000;//我呀
    			6'd31:blank_time<=26'd2_000_000;
    			6'd32:blank_time<=26'd5_000_000;
    			
    			6'd33:blank_time<=26'd2_000_000;//我爱
    			6'd34:blank_time<=26'd2_000_000;
    			6'd35:blank_time<=26'd5_000_000;
    
    			6'd36:blank_time<=26'd10_000_000;//你
    			
    			6'd37:blank_time<=26'd2_000_000;//你爱我
    			6'd38:blank_time<=26'd2_000_000;
    			6'd49:blank_time<=26'd2_000_000;						
    			6'd40:blank_time<=26'd5_000_000;
    	
    			6'd41:blank_time<=26'd2_000_000;	//我爱你蜜雪					
    			6'd42:blank_time<=26'd2_000_000;					
    			6'd43:blank_time<=26'd5_000_000;					
    			6'd44:blank_time<=26'd2_000_000;
    			6'd45:blank_time<=26'd2_000_000;	
    			
    			6'd46:blank_time<=26'd2_000_000;	//冰城甜蜜					
    			6'd47:blank_time<=26'd5_000_000;
    			6'd48:blank_time<=26'd2_000_000;
    			6'd49:blank_time<=26'd2_000_000;
    			
    			6'd50:blank_time<=26'd5_000_000;//蜜
    			default:blank_time<=26'd1_000_000;
    		endcase
    end
    always@(posedge clk,negedge rst_n)begin
    	if(!rst_n)
    		spec_data<=DO;
    	else
    		case(spec_cnt)
    			6'd0:	spec_data <= MI;//你爱我
    			6'd1:	spec_data <= SO;
    			6'd2:	spec_data <= SO;						
    			6'd3:	spec_data <= LA;
    	
    			6'd4:	spec_data <= SO;	//我爱你蜜雪				
    			6'd5:	spec_data <= MI;					
    			6'd6:	spec_data <= DO;					
    			6'd7:	spec_data <= DO;
    			6'd8:	spec_data <= RE;
    
    			6'd9:	spec_data <= MI;	//冰城甜蜜				
    			6'd10:spec_data <= MI;
    			6'd11:spec_data <= RE;
    			6'd12:spec_data <= DO;
    	
    			6'd13:spec_data <= RE;  //蜜
    
    			6'd14:spec_data <= MI;  //你爱我
    			6'd15:spec_data <= SO;
    			6'd16:spec_data <= SO;
    			6'd17:spec_data <= LA;
    
    			6'd18:spec_data <= SO;  //我爱你蜜雪	
    			6'd19:spec_data <= MI;
    			6'd20:spec_data <= DO;
    			6'd21:spec_data <= DO;
    			6'd22:spec_data <= RE;
    
    			6'd23:spec_data <= MI;  //冰城甜蜜
    			6'd24:spec_data <= MI;
    			6'd25:spec_data <= RE;
    			6'd26:spec_data <= RE;
    
    			6'd27:spec_data <= DO;  //蜜
    
    			6'd28:spec_data <= FA;  //你爱
    			6'd29:spec_data <= FA;
    
    			6'd30:spec_data <= FA;  //我呀
    			6'd31:spec_data <= LA;
    			6'd32:spec_data <= LA;
    			
    			6'd33:spec_data <= SO;  //我爱
    			6'd34:spec_data <= SO;
    			6'd35:spec_data <= MI;
    			
    			6'd36:spec_data <= RE;  //你
    			
    			6'd37:spec_data <= MI;  //你爱我
    			6'd38:spec_data <= SO;
    			6'd39:spec_data <= SO;
    			6'd40:spec_data <= LA;
    			
    			6'd41:spec_data <= SO;  //我爱你蜜雪	
    			6'd42:spec_data <= MI;
    			6'd43:spec_data <= DO;
    			6'd44:spec_data <= DO;
    			6'd45:spec_data <= RE;
    
    			6'd46:spec_data <= MI;  //冰城甜蜜
    			6'd47:spec_data <= MI;
    			6'd48:spec_data <= RE;
    			6'd49:spec_data <= RE;
    
    			6'd50:spec_data <= DO;  //蜜
    			default:spec_data <= DO;
    
    		endcase
    end
    //当前音符spec_flag
    always@(posedge clk,negedge rst_n)begin
    	if(!rst_n)
    		spec_flag<=3'd0;
    	else
    		case(spec_data)
    			DO:spec_flag<=3'd1;
    			RE:spec_flag<=3'd2;
    			MI:spec_flag<=3'd3;
    			FA:spec_flag<=3'd4;
    			SO:spec_flag<=3'd5;
    			LA:spec_flag<=3'd6;
    			XI:spec_flag<=3'd7;
    			default:spec_flag<=3'd0;
    		endcase
    end
    
    assign duty_data = spec_data >> 4;
    
    assign end_note = note_cnt== spec_data; //spec_dara对音谱计数
    assign end_spectrum = spec_cnt == NOTE_NUM && inte_cnt == continue_time;
    
    //pwm信号产生模块
    always@(posedge clk or negedge rst_n)begin
    	if(!rst_n)begin
    		status <= 1'b0;
    	end 
    
    	else	
    		status <= (note_cnt >= duty_data) ? 1'b1 : 1'b0; 
    end         
    
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341

    6.蜂鸣器

    module beep_drive (
        input   wire    clk,
        input   wire    rst_n,
        input   wire    flag,       //蜂鸣器开始鸣叫
        input   wire    status,
        output  reg     beep
    );
    
    parameter MAX_TIME = 24'd10_000_000;        //鸣叫时间
    parameter MAX_TIME_MUSIC = 28'd250_000_000; //音乐播放时间
    
    reg [23:0] cnt_time;        //计时
    reg [27:0] cnt_time_music;  //音乐播放计时器
    reg flag_beep_time_out;     // 计时是否结束
    
    
    //音乐播放计时
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            cnt_time_music <= 28'd0;
        end
    
        else if(cnt_time_music < MAX_TIME_MUSIC) begin
            cnt_time_music <= cnt_time_music + 28'd1;
        end
    
        else 
            cnt_time_music <= cnt_time_music;
    end
    
    //蜂鸣器输出
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            cnt_time <= 0;
            beep <= 1;
            flag_beep_time_out <= 1;
        end
    
        else if(!status && cnt_time_music < MAX_TIME_MUSIC) begin
            beep <= 0;
        end
    
        else if(status && cnt_time_music < MAX_TIME_MUSIC) begin
            beep <= 1;
        end
    
        else if(flag && flag_beep_time_out) begin //开始鸣叫
            cnt_time <= MAX_TIME;
            flag_beep_time_out <= 0;
        end
    
        else if(cnt_time >=1 && !flag_beep_time_out) begin
            cnt_time <= cnt_time -24'd1;
            beep <= 0;
        end
    
        else if(cnt_time == 0) begin//计时结束
    		beep <= 1;
    		flag_beep_time_out <= 1;
    	end
    	else begin
    		cnt_time <= cnt_time ;
    		beep <= beep;
            flag_beep_time_out <= flag_beep_time_out;
    	end
    end
    
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    7.顶层模块

    module automatic_machine_top(
        input    wire             clk       ,   //时钟 50M
        input    wire             rst_n     ,   //复位
        input    wire    [2:0]    key       ,   //按键
    
        output    wire             beep     ,   //蜂鸣器
        output    wire    [3:0]    led      ,   //售货机状态灯效
        output    wire    [5:0]    sel      ,   //数码管位选
        output 	  wire    [7:0]    seg      ,   //数码管段选
        output    wire    [6:0]    lan_led      //音乐播放灯效
    
    );
    
    wire            status;         //音乐播放驱使蜂鸣器标志
    wire    [2:0]   key_flag;       //按键消抖完成标志
    wire    [2:0]   key_value;      //按键消抖完成后的按键值
    wire    [4:0]   led_value;      //售货机驱使led模块效果的值
    wire    [6:0]   price_put;      //售货机输出到数码管的投币值
    wire    [6:0]   price_need;     //售货机输出到数码管的商品价格
    wire    [6:0]   price_out;      //售货机输出到数码管的退款
    wire    [2:0]   spec_flag;      //音乐模块输出的音符,用于音乐灯效
    
    
    
    
    //数码管位选模块
    sel_drive inst_sel_drive(
    .clk            (clk)           ,
    .rst_n          (rst_n)         ,
    .price_put      (price_put)     ,      
    .price_need     (price_need)    ,     
    .price_out      (price_out)     ,  
    .sel            (sel)
    );
    
    //数码管段选模块
    seg_drive inst_seg_drive(
    .clk            (clk)           ,	
    .rst_n          (rst_n)         ,
    
    .price_put      (price_put)     ,      
    .price_need     (price_need)    ,     
    .price_out      (price_out)     ,   
    .sel            (sel)           ,          
    .seg            (seg)
    	
    );
    
    //售货机模块
    machine_drive inst_machine_drive(
    .clk        (clk)               ,
    .rst_n      (rst_n)             ,
    .key        ({key_value[2] && key_flag[2], key_value[1] && key_flag[1], key_value[0] && key_flag[0] }),
    
    .led_value  (led_value)         ,
    .price_put  (price_put)         ,
    .price_need (price_need)        ,
    .price_out  (price_out)			 
    );
    
    //led模块
    led_drive inst_led(
    .clk        (clk)               ,
    .rst_n      (rst_n)             ,
    .value      (led_value)         ,
    
    .led        (led)
    );
    
    //音乐模块
    freq_select inst_freq_select
    (
    .clk        (clk   )            ,
    .rst_n      (rst_n )            ,
    	     	
    .status     (status)            , 
    .spec_flag  (spec_flag)
    );
    
    //音乐灯效模块
    lanterns inst_lanterns(
    .clk        (clk   )            ,
    .rst_n      (rst_n )            ,
    .spec_flag  (spec_flag)         ,
            
    .lan_led    (lan_led)
    );
    
    
    //蜂鸣器
    beep_drive inst_beep_drive(
    .clk        (clk)               ,
    .rst_n      (rst_n)             ,
    .flag       ((key_value[2] && key_flag[2]) || ( key_value[1] && key_flag[1]) || (key_value[0] && key_flag[0])),    
    .status     (status)            ,
    .beep       (beep)
    );
    
    //按键消抖
    key_debounce inst_key_debounce_key0(
    .clk        (clk)               ,
    .rst_n      (rst_n)             ,
    .key        (key[0])            ,
              
    .flag       (key_flag[0])       ,
    .key_value  (key_value[0])
    );
    
    key_debounce inst_key_debounce_key1(
    .clk        (clk)               ,
    .rst_n      (rst_n)             ,
    .key        (key[1])            ,
              
    .flag       (key_flag[1])       ,
    .key_value  (key_value[1])
    );
    
    key_debounce inst_key_debounce_key2(
    .clk        (clk)               ,
    .rst_n      (rst_n)             ,
    .key        (key[2])            ,
              
    .flag       (key_flag[2])       ,
    .key_value  (key_value[2])
    );
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127

    七、仿真

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    【JavaScript-BOM】window常见事件,灵活运用定时器
    IPv4 NAT(含Cisco配置)
    CSDN认证C1级别学习笔记 - WEB基础篇
    【Rust】——【面向对象语言的特征】
    React 实现文件分片上传和下载
    4 轮拿下字节 Offer,面试题复盘
    安装虚拟机找不到虚拟网啦1(eth1)不出现
    性能测试从0到1
    CSS特效003:太阳、地球、月球的旋转
    MFC:自绘CListBox,GetText返回一个乱码
  • 原文地址:https://blog.csdn.net/qq_47281915/article/details/124821226