程序代码
顶层文件
module sr_2193_6(
clk,
clk1,
key_add,
key_sub,
pwm_out,
pwm_number);
//顶层文件
input clk,key_add,key_sub;
output clk1,pwm_number,pwm_out;
wire [7:0] pwm_number;
sr_2193_6_1 PWM(clk1,pwm_number,pwm_out);
sr_2193_6_2 fpq(clk,clk1);
sr_2193_6_3 jsq(clk,key_state1,key_state2,pwm_number);
sr_2193_6_4 add(clk, rst, key_add, key_state);
sr_2193_6_5 sub(clk, rst, key_sub, key_state);
//分频器
//加按键消抖
//减按键消抖
//PWM 波形发生器
//占空比计数
endmodule
分频器
module sr_2193_6_2(clk,clk1);
//分频器
//输入端口声明
//输出端口声明
input clk;
output clk1;
reg clk1;
reg [7:0]cnt=10'b0;
//变量数据类型声明
initial
begin
end
clk1=0;
cnt=0;
always@(posedge clk)
//偶数分频器设计,输出信号 clk1 为 100kHz,对 clk 进行 500 分频
begin
if(cnt==10'd249)
begin
cnt <= 0;
clk1 <= ~clk1;
//cnt=249 时重新计数,clk1 取反,得到占空比为 50%的波形信号
end
else cnt <= cnt+1;
end
endmodule
加按键消抖
module
sr_2193_6_4(clk, rst, key_add, key_state1);
//加按键消抖
input
input
input
output
clk;
rst;
key_add;
key_state1;
//时钟信号
//复位信号
//加按键输入信号
//加按键稳定状态,低电平为未按下,高电平为按下状态
reg
reg
reg
[3:0] state_n;
key_state1;
key_temp;
//次态
//用于按键上一次状态存储
wire key_posedge;
wire key_negedge;
//按键上升沿
//按键下降沿
reg
reg
reg
cnt_full;
[19:0]cnt;
en_cnt;
//计数器满时的标志信号
//20 位 2 进制计数器
//使能计数信号
//出现使能计数信号后,才开始计数,其余时刻为清零状态
always@(posedge clk)
key_temp <= key_add;
assign key_negedge = (key_temp) && (!key_add);
assign key_posedge = (!key_temp) && (key_add);
//下降沿
//上升沿
//计数器
always@(posedge clk or negedge rst)
begin
if(!rst)
cnt <= 0;
else if(en_cnt)
cnt <= cnt + 1'b1;
else
end
cnt<=0;
//状态跳转条件
localparam IDLE =4'b0001;
localparam S1 =4'b0010;
localparam S2 =4'b0100;
localparam S3 =4'b1000;
//按键没有按下,空闲状态
//按键按下,消除抖动状态
//按键按下,稳定状态
//按键释放,消除抖动状态
//一段式状态机
always@(posedge clk or negedge rst)
begin
if(!rst)
begin
state_n <= IDLE;
en_cnt <= 1'b0;
key_state1 <= 1'b0;
end
else
begin
case(state_n)
IDLE:
begin
key_state1 <= 1'b0;
if(key_posedge)
begin
state_n <= S1;
en_cnt <= 1'b1;
state_n <= IDLE;
end
else
end
//使能计数器开始计数
S1:
if(cnt_full)
begin
en_cnt <= 1'b0;
//20ms 时间到,计数满后清零,使能计数器进入稳定状态
//如果还没有计完数,就检测到下降沿
//20ms 时间内发生下降沿,使能计数器保持空闲状态(表明只是抖动,不用计数)
//key_flag <= 1'b1;
key_state1 <= 1'b1;
state_n <= S2;
end
else if(key_negedge)
begin
en_cnt <= 1'b0;
state_n <= IDLE;
end
else
state_n <= state_n;
//使能计数器开始计数
//如果还没有计数完,就检测到上升沿
//表示这只是抖动,不用计数,等待下降沿的到来才开始计数
begin
key_state1 <= 1'b1;
if(key_negedge)
begin
state_n <= S3;
en_cnt <= 1'b1;
state_n <= S2;
S2:
S3:
end
else
end
if(cnt_full)
begin
en_cnt <= 1'b0;
state_n <= IDLE;
key_state1 <= 1'b1;
end
else if(key_posedge)
begin
en_cnt <= 1'b0;
state_n <= S2;
end
else
default:
state_n <= state_n;
begin
state_n <= IDLE;
end
endcase
always@(posedge clk or negedge rst)
begin
//计数满信号
if(!rst)
cnt_full <= 1'b0;
else if(cnt == 20'd999_999)
else
cnt_full <= 1'b1;
cnt_full <= 1'b0;
end
end
end
endmodule
减按键消抖
module
sr_2193_6_5(clk, rst, key_sub, key_state2);
//减按键消抖
input
input
input
output
clk;
rst;
key_sub;
key_state2;
//时钟信号
//复位信号
//减按键输入信号
//减按键稳定状态,低电平为未按下,高电平为按下状态
reg
reg
[3:0] state_n;
key_state2;
//次态
reg
key_temp;
//用于按键上一次状态存储
wire key_posedge;
wire key_negedge;
//按键上升沿
//按键下降沿
reg
reg
reg
cnt_full;
[19:0]cnt;
en_cnt;
//计数器满时的标志信号
//20 位 2 进制计数器
//使能计数信号
//出现使能计数信号后,才开始计数,其余时刻为清零状态
always@(posedge clk)
key_temp <= key_sub;
assign key_negedge = (key_temp) && (!key_sub);
assign key_posedge = (!key_temp) && (key_sub);
//下降沿
//上升沿
//计数器
always@(posedge clk or negedge rst)
begin
if(!rst)
cnt <= 0;
else if(en_cnt)
cnt <= cnt + 1'b1;
else
end
cnt<=0;
//状态跳转条件
localparam IDLE =4'b0001;
localparam S1 =4'b0010;
localparam S2 =4'b0100;
localparam S3 =4'b1000;
//按键没有按下,空闲状态
//按键按下,消除抖动状态
//按键按下,稳定状态
//按键释放,消除抖动状态
//一段式状态机
always@(posedge clk or negedge rst)
begin
if(!rst)
begin
state_n <= IDLE;
en_cnt <= 1'b0;
key_state2 <= 1'b0;
end
else
begin
case(state_n)
IDLE:
begin
key_state2 <= 1'b0;
if(key_posedge)
begin
state_n <= S1;
en_cnt <= 1'b1;
state_n <= IDLE;
end
else
end
//使能计数器开始计数
//20ms 时间到,计数满后清零,使能计数器进入稳定状态
//如果还没有计完数,就检测到下降沿
//20ms 时间内发生下降沿,使能计数器保持空闲状态(表明只是抖动,不用计数)
S1:
if(cnt_full)
begin
en_cnt <= 1'b0;
key_state2 <= 1'b1;
state_n <= S2;
end
else if(key_negedge)
begin
en_cnt <= 1'b0;
state_n <= IDLE;
end
else
state_n <= state_n;
begin
key_state2 <= 1'b1;
if(key_negedge)
begin
state_n <= S3;
en_cnt <= 1'b1;
state_n <= S2;
S2:
S3:
end
else
end
if(cnt_full)
begin
en_cnt <= 1'b0;
state_n <= IDLE;
key_state2 <= 1'b1;
end
else if(key_posedge)
begin
en_cnt <= 1'b0;
state_n <= S2;
end
else
default:
state_n <= state_n;
//使能计数器开始计数
//如果还没有计数完,就检测到上升沿
//表示这只是抖动,不用计数,等待下降沿的到来才开始计数
begin
state_n <= IDLE;
end
endcase
end
end
always@(posedge clk or negedge rst)
begin
//计数满信号
if(!rst)
cnt_full <= 1'b0;
else if(cnt == 20'd999_999)
else
cnt_full <= 1'b1;
cnt_full <= 1'b0;
end
endmodule
占空比计数
module sr_2193_6_3(clk,key_state1,key_state2,pwm_number);
//占空比计数
//50MHz 时钟信号
input clk;
input key_state1,key_state2;
output reg[7:0]pwm_number;
//加按键,减按键
//占空比
reg[7:0]i;
reg[7:0]j;
//加计数信号
//减计数信号
initial
begin
end
i=0;
j=0;
pwm_number=0;
//加计数
always@(posedge key_state1)
begin
if(key_state1 == 1'b1)
begin
if(i<8'd100)