You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
4.2 KiB
Verilog
162 lines
4.2 KiB
Verilog
module freq_select(
|
|
input sys_clk ,
|
|
input sys_rst_n ,
|
|
input [1: 0] dev_id ,
|
|
input [3: 0] opcode ,
|
|
input [3: 0] data ,
|
|
|
|
output pwm
|
|
);
|
|
parameter MAX = 24'd15_000_000;//300ms最大数
|
|
parameter TWO_TIGER = 6'd34,
|
|
SKY_CITY = 6'd64;//音符个数
|
|
parameter DO = 16'd47750,//1
|
|
RE = 16'd42550,//2
|
|
MI = 16'd37900,//3
|
|
FA = 16'd37550,//4
|
|
SO = 16'd31850,//5
|
|
LA = 16'd28400,//6
|
|
XI = 16'd25400;//7
|
|
reg start_flag;
|
|
reg [23: 0] cnt_300 ;
|
|
wire add_cnt_300;
|
|
wire end_cnt_300;
|
|
reg [5: 0] cnt_note;
|
|
wire add_cnt_note;
|
|
wire end_cnt_note;
|
|
reg [15: 0] cnt_freq;
|
|
wire add_cnt_freq;
|
|
wire end_cnt_freq;
|
|
reg [5: 0] note ;
|
|
wire [15: 0] duty ;//占空比
|
|
reg [15: 0] X;
|
|
|
|
always @(posedge sys_clk or negedge sys_rst_n)begin
|
|
if(!sys_rst_n)begin
|
|
start_flag <= 1'b0;
|
|
end
|
|
else if(dev_id == 2'd1 && opcode == 4'b0010)begin
|
|
start_flag <= 1'b1;
|
|
end
|
|
else if(dev_id == 2'd1 && opcode == 4'b0001)begin
|
|
start_flag <= 1'b0;
|
|
end
|
|
else begin
|
|
start_flag <= start_flag;
|
|
end
|
|
end
|
|
//300ms计数器设计
|
|
always @(posedge sys_clk or negedge sys_rst_n) begin
|
|
if(!sys_rst_n)begin
|
|
cnt_300 <= 24'd0;
|
|
end
|
|
else if(add_cnt_300)begin
|
|
if(end_cnt_300)begin
|
|
cnt_300 <= 24'd0;
|
|
end
|
|
else begin
|
|
cnt_300 <= cnt_300 + 1'd1;
|
|
end
|
|
end
|
|
else if(dev_id == 2'd1 && opcode == 4'b0001)begin
|
|
cnt_300 <= 24'd0;
|
|
end
|
|
else begin
|
|
cnt_300 <= cnt_300;
|
|
end
|
|
end
|
|
assign add_cnt_300 = start_flag;
|
|
assign end_cnt_300 = add_cnt_300 && (cnt_300 == MAX - 1'd1);//要么计数完成,要么重新开始指令有效
|
|
//34个音符计数器设计
|
|
always @(posedge sys_clk or negedge sys_rst_n)begin
|
|
if(!sys_rst_n)begin
|
|
cnt_note <= 6'd0;
|
|
end
|
|
else if(add_cnt_note)begin
|
|
if(end_cnt_note)begin
|
|
cnt_note <= 6'd0;
|
|
end
|
|
else begin
|
|
cnt_note <= cnt_note + 1'd1;
|
|
end
|
|
end
|
|
else if(dev_id == 2'd1 && opcode == 4'b0001)begin
|
|
cnt_note <= 6'd0;
|
|
end
|
|
else begin
|
|
cnt_note <= cnt_note;
|
|
end
|
|
end
|
|
assign add_cnt_note = end_cnt_300;
|
|
assign end_cnt_note = add_cnt_note && (cnt_note == note - 1'd1);
|
|
//每个音符频率计数器
|
|
always @(posedge sys_clk or negedge sys_rst_n)begin
|
|
if(!sys_rst_n)begin
|
|
cnt_freq <= 16'd0;
|
|
end
|
|
else if(add_cnt_freq)begin
|
|
if(end_cnt_freq)begin
|
|
cnt_freq <= 16'd0;
|
|
end
|
|
else begin
|
|
cnt_freq <= cnt_freq + 1'd1;
|
|
end
|
|
end
|
|
else if(dev_id == 2'd1 && opcode == 4'b0001)begin
|
|
cnt_freq <= 16'd0;
|
|
end
|
|
else begin
|
|
cnt_freq <= cnt_freq;
|
|
end
|
|
end
|
|
assign add_cnt_freq = start_flag;
|
|
assign end_cnt_freq = add_cnt_freq && (cnt_freq == X - 1);
|
|
//查找表
|
|
always @(*)begin
|
|
case(data)
|
|
4'b0001: note = TWO_TIGER;
|
|
4'b0010: note = SKY_CITY;
|
|
endcase
|
|
end
|
|
always @(*)begin
|
|
case(cnt_note)
|
|
6'd0 : X = DO;//1
|
|
6'd1 : X = RE;//2
|
|
6'd2 : X = MI;//3
|
|
6'd3 : X = DO;//1
|
|
6'd4 : X = DO;//1
|
|
6'd5 : X = RE;//2
|
|
6'd6 : X = MI;//3
|
|
6'd7 : X = DO;//1
|
|
6'd8 : X = MI;//3
|
|
6'd9 : X = FA;//4
|
|
6'd10 : X = SO;//5
|
|
6'd11 : X = MI;//3
|
|
6'd12 : X = FA;//4
|
|
6'd13 : X = SO;//5
|
|
6'd14 : X = SO;//5
|
|
6'd15 : X = LA;//6
|
|
6'd16 : X = SO;//5
|
|
6'd17 : X = FA;//4
|
|
6'd18 : X = MI;//3
|
|
6'd19 : X = DO;//1
|
|
6'd20 : X = SO;//5
|
|
6'd21 : X = LA;//6
|
|
6'd22 : X = SO;//5
|
|
6'd23 : X = FA;//4
|
|
6'd24 : X = MI;//3
|
|
6'd25 : X = DO;//1
|
|
6'd26 : X = RE;//2
|
|
6'd27 : X = SO;//5
|
|
6'd28 : X = DO;//1
|
|
6'd29 : X = DO;//1
|
|
6'd30 : X = RE;//2
|
|
6'd31 : X = SO;//5
|
|
6'd32 : X = DO;//1
|
|
6'd33 : X = DO;//1
|
|
default: X = DO;//1
|
|
endcase
|
|
end
|
|
assign duty = X >> 1;//占空比是1/2
|
|
assign pwm = (cnt_freq >= duty) ? 1'b0: 1'b1;
|
|
endmodule
|