基于FPGA的可调时钟与闹钟
在上一篇博客的方案上的改进版本
代码部分
module top
/
//*********************************************************//
//* Author : Petter *//
//* Time : 2022.06.20 *//
//* IC : EP4CE6F17C8 *//
//* Project : demo_clock *//
//* Module : top *//
//* *//
//*********************************************************//
/
/********************************************************************************************/
module top(
input wire clk,
input wire rst_n,
input wire[1:0] key_in,
input wire key_add_in,
output [5:0] sel, //位选输出
output [6:0] ment, //段选输出
output pot, //小数点
output ring, //蜂鸣器
output [3:0] led //指示灯
);
wire[2:0] key_out;
wire[3:0] sys;
wire[3:0] mov;
wire add;
wire[23:0] data;
wire ring_ctrl;
/********************************************************************************************/
key key(
.clk (clk),
.rst_n (rst_n),
.key_in (key_in),
.key_add_in (key_add_in),
.key_out (key_out),
);
state state(
.clk (clk),
.rst_n (rst_n),
.key_out (key_out),
.sys (sys),
.mov (mov),
.add (add)
);
ctrl ctrl(
.clk (clk),
.rst_n (rst_n),
.sys (sys),
.mov (mov),
.add (add),
.data (data),
.ring_ctrl (ring_ctrl),
.led (led)
);
display display(
.clk (clk),
.rst_n (rst_n),
.sys (sys),
.mov (mov),
.data (data),
.sel (sel),
.ment (ment),
.pot (pot)
);
buzzer buzzer(
.clk (clk),
.ring_ctrl (ring_ctrl),
.ring (ring)
);
/****************************************************************************************************************/
endmodule
module key
/
//*********************************************************//
//* Author : Petter *//
//* Time : 2022.06.20 *//
//* IC : EP4CE6F17C8 *//
//* Project : demo_clock *//
//* Module : key *//
//* *//
//*********************************************************//
/
/********************************************************************************************/
/******按键消抖模块******/
module key(
input wire clk,
input wire rst_n,
input wire[1:0] key_in, //state和move控制
input wire key_add_in, //add控制设计为可以长按
output wire[2:0] key_out //按键模块信号输出
);
localparam DELAY_TWENTY=999_999;
wire[1:0] ctrl; //消抖后信号
reg[19:0] cnt_delay; //延时计数器
wire add_cnt_delay; //延时计数器"+1"
wire end_cnt_delay; //延时计数器结束
reg key_flag; //标志信号
reg[1:0] key_r0; //延时一拍
reg[1:0] key_r1; //延时两拍
reg[1:0] key_r2; //延时三拍
reg[1:0] key_down; //消抖后信号
wire n_edge; //下降沿
wire p_edge; //上升沿
/********************************************************************************************/
//边沿检测
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)begin
key_r0 <= 0;
key_r1 <= 0;
key_r2 <= 0; end
else begin
key_r0 <= key_in;
key_r1 <= key_r0;
key_r2 <= key_r1; end
end
//按位相与,识别下降沿和上升沿
assign n_edge = ~key_r1 & key_r2?1'b1:1'b0; //下降沿
assign p_edge = key_r1 & ~key_r2?1'b1:1'b0; //上升沿
/********************************************************************************************/
//当检测到下降沿,key_flag为1
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
key_flag <= 1'b0; end
else if(n_edge) begin
key_flag <= 1'b1; end
else if(end_cnt_delay) begin
key_flag <= 1'b0; end //延时计数器计数到20ms后没有检测到下降沿将不再次计数
else begin
key_flag <= key_flag; end
end
/********************************************************************************************/
//延时处理并输出信号,当检测到下降沿开始计数,计数到20ms结束
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_delay <= 20'd0; end
else if(add_cnt_delay) begin
if(end_cnt_delay || p_edge) begin //p_edge是为波峰电时间段不计数
cnt_delay <= 20'd0; end
else begin
cnt_delay <= cnt_delay + 20'd1; end end
else begin
cnt_delay <= cnt_delay; end
end
assign add_cnt_delay = key_flag;
assign end_cnt_delay = add_cnt_delay && cnt_delay == DELAY_TWENTY;
/********************************************************************************************/
//消抖后信号
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)begin
key_down <= 0; end
else if(end_cnt_delay)begin
key_down <= ~key_r2; end
else begin
key_down <= 0; end
end
/********************************************************************************************/
/********************************************************************************************/
/***连加***/
localparam HALF = 24_999_999; //500ms
reg[23:0] cnt_HALF; //延时0.5s计数器
wire add_cnt_HALF;
wire end_cnt_HALF;
/********************************************************************************************/
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_HALF<= 24'd0;end
else if(add_cnt_HALF) begin
if(end_cnt_HALF) begin
cnt_HALF <= 24'd0; end
else begin
cnt_HALF <= cnt_HALF + 24'd1; end end
else begin
cnt_HALF <= cnt_HALF; end
end
assign add_cnt_HALF = ~key_add_in; //按下为低电平
assign end_cnt_HALF = add_cnt_HALF && cnt_HALF == HALF;
/********************************************************************************************/
//key_out[0]~add~pin(key_add_in);
//key_out[1]~move_ctrl~pin(key_in[0])
//key_out[2]~sys_ctrl~pin(key_in[1])
assign key_out = {key_down,end_cnt_HALF};//模块信号输出,
/********************************************************************************************/
endmodule
module state
/
//*********************************************************//
//* Author : Petter *//
//* Time : 2022.06.20 *//
//* IC : EP4CE6F17C8 *//
//* Project : demo_clock *//
//* Module : state *//
//* *//
//*********************************************************//
/
/********************************************************************************************/
/******状态时序控制模块******/
module state(
input wire clk,
input wire rst_n,
input wire[2:0] key_out,
output wire[3:0] sys,
output wire[3:0] mov,
output wire add
);
//
/********************************************************************************************/
//系统整体状态控制,用状态机写
reg[3:0] sys_state_c; //现态
reg[3:0] sys_state_n; //次态
reg[3:0] sys_out;
wire sys_idle_to_s1;//-->S1
wire sys_s1_to_s2; //-->S2
wire sys_s2_to_s3; //-->S3
wire sys_state_re; //-->reset
localparam sys_IDLE= 0; //'0':复位态;'1':state run;'2':state change;'3':state alarm
localparam sys_S1= 1;
localparam sys_S2= 2;
localparam sys_S3= 3;
/********************************************************************************************/
//时序同步
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
sys_state_c <= sys_IDLE; end
else begin
sys_state_c <= sys_state_n; end
end
/********************************************************************************************/
//状态转移
always@(*) begin
case(sys_state_c)
sys_IDLE: begin
if(sys_idle_to_s1) begin
sys_state_n <= sys_S1; end
else begin
sys_state_n <= sys_state_c; end
end
sys_S1: begin
if(sys_s1_to_s2) begin
sys_state_n <= sys_S2; end
else begin
sys_state_n <= sys_state_c; end
end
sys_S2: begin
if(sys_s2_to_s3) begin
sys_state_n <= sys_S3; end
else begin
sys_state_n <= sys_state_c; end
end
sys_S3: begin
if(sys_state_re) begin
sys_state_n <= sys_S1; end
else begin
sys_state_n <= sys_state_c; end
end
default: begin
sys_state_n <= sys_IDLE; end
endcase
end
/********************************************************************************************/
//状态转移条件
assign sys_idle_to_s1 = sys_state_c==sys_IDLE;
assign sys_s1_to_s2 = sys_state_c==sys_S1 && key_out[2]==1;
assign sys_s2_to_s3 = sys_state_c==sys_S2 && key_out[2]==1;
assign sys_state_re = sys_state_c==sys_S3 && key_out[2]==1;
/********************************************************************************************/
//输出信号控制
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
sys_out <= 4'd0; end
else if(sys_state_c==sys_S1) begin
sys_out <= 4'd1; end
else if(sys_state_c==sys_S2) begin
sys_out <= 4'd2; end
else if(sys_state_c==sys_S3) begin
sys_out <= 4'd3; end
else begin
sys_out <= sys_out; end
end
assign sys = sys_out;
/********************************************************************************************/
/********************************************************************************************/
//move控制,用计数器写
reg[3:0] move; //'1':change second;'2':change minute;'3':change hour
wire add_move;
wire reset_move;
wire end_move;
/********************************************************************************************/
//move
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
move <= 4'd0; end
else if(reset_move ) begin
move <= 4'd0; end
else if(add_move ) begin
if(end_move ) begin
move <= 4'd1; end
else begin
move <= move + 4'd1; end end
else begin
move <= move ; end
end
assign add_move = key_out[1];
assign reset_move = key_out[2];
assign end_move = add_move && move == 4'd3;
assign mov = move;
/********************************************************************************************/
//add
assign add = key_out[0];
/********************************************************************************************/
endmodule
module ctrl
/
//*********************************************************//
//* Author : Petter *//
//* Time : 2022.06.20 *//
//* IC : EP4CE6F17C8 *//
//* Project : demo_clock *//
//* Module : ctrl *//
//* *//
//*********************************************************//
/
/********************************************************************************************/
module ctrl(
input wire clk,
input wire rst_n,
input wire[3:0] sys,
input wire[3:0] mov,
input wire add,
output wire[23:0] data,
output wire ring_ctrl,//蜂鸣器
output reg [3:0] led
);
reg[23:0] data_out;
//clock
reg[27:0] cnt_div_s; //49_999_999 1s
reg[7:0] cnt_s; //时钟second计数器
reg[7:0] cnt_min; //时钟minute计数器
reg[7:0] cnt_h; //时钟hour计数器
wire add_cnt_div_s;
wire end_cnt_div_s;
wire add_cnt_s;
wire add_cnt_min;
wire add_cnt_h;
wire end_cnt_s;
wire end_cnt_min;
wire end_cnt_h;
wire stop_cnt_s;
wire stop_cnt_min;
wire stop_cnt_h;
wire change_cnt_s;
wire change_cnt_min;
wire change_cnt_h;
//alarm
reg[7:0] alarm_s; //闹钟second计数器
reg[7:0] alarm_min; //闹钟minute计数器
reg[7:0] alarm_h; //闹钟hour计数器
wire add_alarm_s;
wire add_alarm_min;
wire add_alarm_h;
wire end_alarm_s;
wire end_alarm_min;
wire end_alarm_h;
wire flag_s;
wire flag_min;
wire flag_h;
wire flag_ring; //蜂鸣器鸣叫信号
//flag
wire clock; //标志数码管显示数据为时钟
wire alarm; //标志数码管显示数据为闹钟
/****************************************************************************************************************/
//时钟功能计数器
//1s计数器
//cnt_div_s
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_div_s <= 28'd0; end
else if(add_cnt_div_s) begin
if(end_cnt_div_s) begin
cnt_div_s <= 28'd0; end
else begin
cnt_div_s <= cnt_div_s + 28'd1; end
end
end
assign add_cnt_div_s = sys == 1 || sys == 3; //'1'&'3'态驱动时钟
assign end_cnt_div_s = add_cnt_div_s && cnt_div_s == 28'd49_999_999; //28'd1_999_999;
//second计数器
//cnt_s
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_s <= 8'd0; end
else if(add_cnt_s) begin
if(end_cnt_s) begin
cnt_s <= 8'd0; end
else begin
cnt_s <= cnt_s + 8'd1; end
end
else if(stop_cnt_s) begin
if(change_cnt_s) begin
cnt_s <= cnt_s + 8'd1; end
else if(cnt_s== 8'd60) begin
cnt_s <= 8'd0; end
else begin
cnt_s <= cnt_s; end
end
end
assign add_cnt_s = end_cnt_div_s;
assign end_cnt_s = add_cnt_s && cnt_s == 8'd59;
assign stop_cnt_s = sys == 2;
assign change_cnt_s = mov == 1 && add;
//minute计数器
//cnt_min
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_min <= 8'd0; end
else if(add_cnt_min) begin
if(end_cnt_min) begin
cnt_min <= 8'd0; end
else begin
cnt_min <= cnt_min + 8'd1; end
end
else if(stop_cnt_min) begin
if(change_cnt_min) begin
cnt_min <= cnt_min + 8'd1; end
else if(cnt_min== 8'd60) begin
cnt_min <= 8'd0; end
else begin
cnt_min <= cnt_min; end
end
end
assign add_cnt_min = end_cnt_s;
assign end_cnt_min = (add_cnt_min && cnt_min== 8'd59) || (add_cnt_min && cnt_min == 8'd59 && cnt_s == 8'd59);
assign stop_cnt_min = sys == 2;
assign change_cnt_min = mov == 2 && add;
//hour计数器
//cnt_h
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_h <= 8'd0; end
else if(add_cnt_h) begin
if(end_cnt_h) begin
cnt_h <= 8'd0; end
else begin
cnt_h <= cnt_h + 8'd1; end
end
else if(stop_cnt_h) begin
if(change_cnt_h) begin
cnt_h <= cnt_h + 8'd1; end
else if( cnt_h== 8'd24) begin
cnt_h <= 8'd0; end
else begin
cnt_h <= cnt_h; end
end
end
assign add_cnt_h = end_cnt_min && end_cnt_s;
assign end_cnt_h = add_cnt_h && cnt_h == 8'd23 && cnt_min == 8'd59 && cnt_s == 8'd59;
assign stop_cnt_h = sys == 2;
assign change_cnt_h = mov == 3 && add;
/****************************************************************************************************************/
//闹钟功能计数器
//alarm_s
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
alarm_s <= 8'd0; end
else if(add_alarm_s) begin
if(end_alarm_s) begin
alarm_s <= 8'd0; end
else begin
alarm_s <= alarm_s + 8'd1; end
end
end
assign add_alarm_s = mov == 1 && sys == 3 && add;
assign end_alarm_s = add_alarm_s && alarm_s == 8'd59;
//alarm_min
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
alarm_min <= 8'd0; end
else if(add_alarm_min) begin
if(end_alarm_min) begin
alarm_min <= 8'd0; end
else begin
alarm_min <= alarm_min + 8'd1; end
end
end
assign add_alarm_min = mov == 2 && sys == 3 && add;
assign end_alarm_min = add_alarm_min && alarm_min == 8'd59;
//alarm_h
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
alarm_h <= 8'd6; end
else if(add_alarm_h) begin
if(end_alarm_h) begin
alarm_h <= 8'd0; end
else begin
alarm_h <= alarm_h + 8'd1; end
end
end
assign add_alarm_h = mov == 3 && sys == 3 && add;
assign end_alarm_h = add_alarm_h && alarm_h == 8'd23;
//ring_data
reg ring_data;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin //强制复位
ring_data <= 1'b0; end
else if(flag_ring) begin
ring_data <= 1'b1; end
else if(add) begin //手动关闭buzzer
ring_data <= 1'b0; end
else begin
ring_data <= ring_data; end
end
assign flag_s = cnt_s == alarm_s;
assign flag_min = cnt_min == alarm_min;
assign flag_h = cnt_h == alarm_h;
assign flag_ring = flag_s && flag_min && flag_h;
assign ring_ctrl = ring_data; //ring控制信号输出
/********************************************************************************************/
//数码管显示控制
assign clock = sys == 1 || sys == 2;
assign alarm = sys == 3;
//输出数据选择
always@(posedge clk)
begin
if(!rst_n) begin
data_out <= 0; end
else if(clock) begin
data_out <= {cnt_h,cnt_min,cnt_s}; end
else if(alarm) begin
data_out <= {alarm_h,alarm_min,alarm_s}; end
else begin
data_out <= data_out; end
end
assign data = data_out;
/********************************************************************************************/
//led
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
led <= 4'b1111; end
else if(sys == 2) begin
led <= 4'b0011; end
else if(sys == 3) begin
led <= 4'b1100; end
else if(sys == 1) begin
if(cnt_s % 2 == 0) begin
led <= 4'b1100; end
else if(cnt_s % 2 == 1) begin
led <= 4'b0011; end end
else begin
led <= led; end
end
/********************************************************************************************/
endmodule
module display
/
//*********************************************************//
//* Author : Petter *//
//* Time : 2022.06.20 *//
//* IC : EP4CE6F17C8 *//
//* Project : demo_clock *//
//* Module : display *//
//* *//
//*********************************************************//
/
/********************************************************************************************/
module display(
input wire clk,
input wire rst_n,
input wire[3:0] mov,
input wire[3:0] sys,
input wire[23:0] data,
output reg[5:0] sel, //位选输出
output reg[6:0] ment, //段选输出
output reg pot //小数点
);
reg[19:0] cnt_div_ms; //49_999 1ms,数码管扫描频率
reg[3:0] cnt_sel; //数码管扫描计数器
reg[3:0] data_sL; //second低位
reg[3:0] data_sH; //second高位
reg[3:0] data_minL; //minute低位
reg[3:0] data_minH; //minute高位
reg[3:0] data_hL; //hour低位
reg[3:0] data_hH; //hour高位
reg[3:0] data_ment; //数码管数据传递中间参量
wire add_cnt_div_ms;
wire end_cnt_div_ms;
wire add_cnt_sel;
wire end_cnt_sel;
/********************************************************************************************/
//高低位数据分离
always@(posedge clk)
begin
data_sL <= data[7:0] % 8'd10;
data_sH <= data[7:0] / 8'd10;
data_minL <= data[15:8] % 8'd10;
data_minH <= data[15:8] / 8'd10;
data_hL <= data[23:16] % 8'd10;
data_hH <= data[23:16] / 8'd10;
end
//显示译码
always@(posedge clk)
begin
case(data_ment)
4'd0 : ment <= 7'b1_000_000;
4'd1 : ment <= 7'b1_111_001;
4'd2 : ment <= 7'b0_100_100;
4'd3 : ment <= 7'b0_110_000;
4'd4 : ment <= 7'b0_011_001;
4'd5 : ment <= 7'b0_010_010;
4'd6 : ment <= 7'b0_000_010;
4'd7 : ment <= 7'b1_111_000;
4'd8 : ment <= 7'b0_000_000;
4'd9 : ment <= 7'b0_010_000;
default : ment <= 7'b1_000_000;
endcase
end
//1ms计数器
//cnt_div_ms
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_div_ms <= 20'd0; end
else if(add_cnt_div_ms) begin
if(end_cnt_div_ms) begin
cnt_div_ms <= 20'd0; end
else begin
cnt_div_ms <= cnt_div_ms + 20'd1; end end
else begin
cnt_div_ms <= cnt_div_ms; end
end
assign add_cnt_div_ms = rst_n;
assign end_cnt_div_ms = add_cnt_div_ms && cnt_div_ms == 20'd49_999; //1ms
//位选计数器
//cnt_sel
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_sel <= 4'd0; end
else if(add_cnt_sel) begin
if(end_cnt_sel) begin
cnt_sel <= 4'd0; end
else begin
cnt_sel <= cnt_sel + 4'd1; end end
else begin
cnt_sel <= cnt_sel; end
end
assign add_cnt_sel = end_cnt_div_ms;
assign end_cnt_sel = add_cnt_sel && cnt_sel == 4'd5;
//数据传递
always@(posedge clk)
begin
case(cnt_sel)
4'd0 : begin data_ment <= data_sL;
pot<= 1;end
4'd1 : begin data_ment <= data_sH;
pot<= 1;end
4'd2 : begin data_ment <= data_minL;
pot<= 0;end
4'd3 : begin data_ment <= data_minH;
pot<= 1;end
4'd4 : begin data_ment <= data_hL;
pot<= 0; end
4'd5 : begin data_ment <= data_hH;
pot<= 1;end
default data_ment <= 4'd0;
endcase
end
/****************************************************************************************************************/
/***数码管扫描***/
reg [27:0] cnt_div_s;
wire add_cnt_div_s;
wire end_cnt_div_s;
reg [3:0] cnt_choice;
wire add_cnt_choice;
wire end_cnt_choice;
//1s计数器
//cnt_div_s
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_div_s <= 28'd0; end
else if(add_cnt_div_s) begin
if(end_cnt_div_s) begin
cnt_div_s <= 28'd0; end
else begin
cnt_div_s <= cnt_div_s + 28'd1; end
end
end
assign add_cnt_div_s = rst_n;
assign end_cnt_div_s = add_cnt_div_s && cnt_div_s == 28'd9_999_999;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_choice <= 4'd0; end
else if(add_cnt_choice) begin
if(end_cnt_choice) begin
cnt_choice <= 4'd0; end
else begin
cnt_choice <= cnt_choice + 4'd1; end end
end
assign add_cnt_choice = end_cnt_div_s;
assign end_cnt_choice = add_cnt_choice && cnt_choice == 4'd1;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
sel <= 6'b000_000; end
else if(sys == 1) begin
case(cnt_sel)
4'd0 : sel <= 6'b111_110;
4'd1 : sel <= 6'b111_101;
4'd2 : sel <= 6'b111_011;
4'd3 : sel <= 6'b110_111;
4'd4 : sel <= 6'b101_111;
4'd5 : sel <= 6'b011_111;
default : sel <= 6'b111_110;
endcase end
else if(sys == 2 || sys == 3) begin
if(cnt_choice == 0) begin
case(cnt_sel)
4'd0 : sel <= 6'b111_110;
4'd1 : sel <= 6'b111_101;
4'd2 : sel <= 6'b111_011;
4'd3 : sel <= 6'b110_111;
4'd4 : sel <= 6'b101_111;
4'd5 : sel <= 6'b011_111;
default : sel <= 6'b111_110;
endcase end
else if(cnt_choice == 1) begin
if(mov == 0) begin
case(cnt_sel)
4'd0 : sel <= 6'b111_110;
4'd1 : sel <= 6'b111_101;
4'd2 : sel <= 6'b111_011;
4'd3 : sel <= 6'b110_111;
4'd4 : sel <= 6'b101_111;
4'd5 : sel <= 6'b011_111;
default : sel <= 6'b111_111;
endcase end
else if(mov == 1) begin
case(cnt_sel)
4'd0 : sel <= 6'b111_111;
4'd1 : sel <= 6'b111_111;
4'd2 : sel <= 6'b111_011;
4'd3 : sel <= 6'b110_111;
4'd4 : sel <= 6'b101_111;
4'd5 : sel <= 6'b011_111;
default : sel <= 6'b111_111;
endcase end
else if(mov == 2) begin
case(cnt_sel)
4'd0 : sel <= 6'b111_110;
4'd1 : sel <= 6'b111_101;
4'd2 : sel <= 6'b111_111;
4'd3 : sel <= 6'b111_111;
4'd4 : sel <= 6'b101_111;
4'd5 : sel <= 6'b011_111;
default : sel <= 6'b111_111;
endcase end
else if(mov == 3) begin
case(cnt_sel)
4'd0 : sel <= 6'b111_110;
4'd1 : sel <= 6'b111_101;
4'd2 : sel <= 6'b111_011;
4'd3 : sel <= 6'b110_111;
4'd4 : sel <= 6'b111_111;
4'd5 : sel <= 6'b111_111;
default : sel <= 6'b111_111;
endcase end
end
end
end
/****************************************************************************************************************/
endmodule
module buzzer
module buzzer(
input wire clk,
input wire ring_ctrl,
output reg ring
);
reg [22:0] tone;
reg [14:0] counter;
wire [ 6:0] ramp = (tone[22] ? tone[21:15] : ~tone[21:15]);
wire [14:0] clkdivider = {2'b01, ramp, 6'b000_000};
always@(posedge clk)
begin
tone <= tone + 1;
end
always@(posedge clk)
begin
if(counter == 0)begin
counter <= clkdivider; end
else begin
counter <= counter - 1; end
end
always@(posedge clk)
begin
if(ring_ctrl == 1)begin
if(counter == 0) begin
ring <= ~ ring; end end
else if(ring_ctrl == 0) begin
ring <= 1; end
end
endmodule