先讲讲里面的矩阵键盘,矩阵键盘列有下拉电阻,默认全为0000,默认行输入为1111,当有按键按下的时候,列输入会被拉高,这时控制行的输出做行扫描,电子琴用key_flag_r0电平作为使能,这里用key_flag消抖后与键值进行按位与,作为相应按键的判断条件。
module juzhen
(
input clk,
input rst_n,
input [3:0] col_data,
output reg [3:0] row_data,
output key_flag, //the mark of key is pressed
output reg [3:0] key_value,
output reg key_flag_r0
);
parameter SCAN_IDLE = 3'b000;
parameter SCAN_JITTER= 3'b001;
parameter SCAN_COL0 = 3'b011;
parameter SCAN_COL1 = 3'b010;
parameter SCAN_COL2 = 3'b110;
parameter SCAN_COL3 = 3'b100;
parameter SCAN_READ = 3'b101;
parameter SCAN_JTTTER2= 3'b111;
reg [19:0] cnt;
reg [2:0] current_state;
reg [2:0] next_state;
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin cnt<=0; end
else
begin
if(cnt>=20'h7ffff) begin cnt<=0;end
else cnt<=cnt+1;end
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
current_state <= SCAN_IDLE;
else if(cnt == 20'h7ffff) current_state <= next_state;
end
always@*
begin case(current_state)
SCAN_IDLE : //init
if(col_data != 4'b0000) next_state = SCAN_JITTER; //初始化
else next_state = SCAN_IDLE;
SCAN_JITTER: //escape the jitter
if(col_data != 4'b0000) next_state = SCAN_COL0;//消除抖动
else next_state = SCAN_IDLE;
SCAN_COL0 : //1th row
if(col_data != 4'b0000) next_state = SCAN_READ;else next_state = SCAN_COL1;
SCAN_COL1 : //2th row
if(col_data != 4'b0000) next_state = SCAN_READ;else next_state = SCAN_COL2;
SCAN_COL2 : //3th row
if(col_data != 4'b0000) next_state = SCAN_READ;else next_state = SCAN_COL3;
SCAN_COL3 : //4th row
if(col_data != 4'b0000) next_state = SCAN_READ;else next_state = SCAN_IDLE;
SCAN_READ : //lock the vaule
if(col_data != 4'b0000) next_state = SCAN_JTTTER2;else next_state = SCAN_IDLE;
SCAN_JTTTER2: //when your hand is gone
if(col_data != 4'b0000) next_state = SCAN_JTTTER2;else next_state = SCAN_IDLE;
endcase
end
reg [3:0] col_data_r;
reg [3:0] row_data_r;
always@(posedge clk or negedge rst_n)
begin if(!rst_n) begin row_data <= 4'b1111;key_flag_r0 <= 0;end
else if(cnt == 20'h7ffff)begin
case(next_state)
SCAN_IDLE : begin row_data <= 4'b1111;key_flag_r0 <= 0;end //SCAN_JITTER:
SCAN_COL0 : row_data <= 4'b0001;
SCAN_COL1 : row_data <= 4'b0010;
SCAN_COL2 : row_data <= 4'b0100;
SCAN_COL3 : row_data <= 4'b1000;
SCAN_READ : begin
row_data_r <= row_data;
col_data_r <= col_data;
key_flag_r0 <= 1;
end
//SCAN_JTTTER2:
default:; //default vaule
endcase
end
end
always @(posedge clk or negedge rst_n)
begin if(!rst_n)key_value <= 0;
else if(cnt == 20'h7fff)
begin
if(key_flag_r0 == 1'b1) //the mark of key is pressed
begin
case ({row_data_r,col_data_r}) //row_data Row, col_data Col
8'b0001_0001: key_value <= 4'd0;
8'b0010_0001: key_value <= 4'd1;
8'b0100_0001: key_value <= 4'd2;
8'b1000_0001: key_value <= 4'd3;
8'b0001_0010: key_value <= 4'd4;
8'b0010_0010: key_value <= 4'd5;
8'b0100_0010: key_value <= 4'd6;
8'b1000_0010: key_value <= 4'd7;
8'b0001_0100: key_value <= 4'd8;
8'b0010_0100: key_value <= 4'd9;
8'b0100_0100: key_value <= 4'd10;
8'b1000_0100: key_value <= 4'd11;
8'b0001_1000: key_value <= 4'd12;
8'b0010_1000: key_value <= 4'd13;
8'b0100_1000: key_value <= 4'd14;
8'b1000_1000: key_value <= 4'd15;
default : key_value <= key_value;
endcase
end
else
key_value <= key_value;
end
end
//Capture the falling endge
reg key_flag_r2,key_flag_r1;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
key_flag_r1 <= 0;
key_flag_r2 <= 0;
end
else
begin
key_flag_r1 <= key_flag_r0;
key_flag_r2 <= key_flag_r1;
end
end
assign key_flag = key_flag_r2 & ~key_flag_r1; //when your hand is gone
endmodule
幅度相位 波形选择频率控制模块
module ddsout
(
output reg [7:0]data,
input cs,
output [3:0] row,
input [3:0]col,
input sclk,
input rst_n,
input clk
);
wire [3:0] key_value;
juzhen xiaodou
(
.clk(clk),
.rst_n(rst_n),
.col_data(col),
.row_data(row),
.key_flag(key_flag),
.key_value(key_value)
);
reg [8:0] adress;
reg[3:0]cnt1,cnt2;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)begin cnt1<=1;end
else if(cnt1==15)cnt1<=1;
else if(key_value==2&key_flag==1) cnt1<=cnt1+1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)begin cnt2<=1;end
else if(cnt2==15)cnt2<=1;
else if(key_value==6&key_flag==1) cnt2<=cnt2+1;
end
reg [15:0] adress_r;
always@(posedge sclk or negedge rst_n)
begin
if(!rst_n) adress_r<=0;
else adress_r<=adress_r+cnt1;频率控制字
end
always @(posedge sclk)
if(!rst_n)adress<=0;
else if(adress>511)adress=0;
else
adress<=adress_r[15:7]+cnt2;相位控制字
wire [7:0]sina_data,san_data,fang_data,ju_data;
sina sina_ut
(
.Address(adress),
.OutClock (sclk),
.OutClockEn(cs),
.Reset(0),
.Q(sina_data)
);
san san_ut
(
.Address(adress),
.OutClock (sclk),
.OutClockEn(cs),
.Reset(0),
.Q(san_data)
);
fang fang_ut
(
.Address(adress),
.OutClock (sclk),
.OutClockEn(cs),
.Reset(0),
.Q(fang_data)
);
ju ju_ut
(
.Address(adress),
.OutClock (sclk),
.OutClockEn(cs),
.Reset(0),
.Q(ju_data)
); //ROM模块调用,可以参考这位大神的调用http://www.cnblogs.com/tony-ning/p/4971053.html
reg [1:0]cnt3;//波形选择
reg[1:0]cnt4;//幅度调节
always@(posedge clk or negedge rst_n)
if(~rst_n)cnt3<=0;
else if(key_value==3&key_flag==1)
cnt3<=cnt3+1;
else if(cnt3>3)cnt3<=0;
else cnt3<=cnt3;
always@(posedge clk or negedge rst_n)
if(!rst_n)cnt4<=0;
else if(key_value==7&key_flag==1)
cnt4<=cnt4+1;
else if(cnt4>3)cnt4<=0;
else cnt4<=cnt4;
reg [7:0]data_reg;
always @(cnt3)
if(! rst_n) data_reg<=sina_data;
else begin
case(cnt3)
0:data_reg<=sina_data;
1:data_reg<=san_data;
2:data_reg<=fang_data;
3:data_reg<=ju_data;
default:data_reg<=sina_data;
endcase
end
always@(posedge sclk )
if( !rst_n)data=data_reg;
else begin
case(cnt4)
0:data=data_reg;
1:data=data_reg>>1;
2:data=data_reg>>2;
3:data=data_reg>>3;
default:data=data_reg;
endcase
end
endmodule
DAC输出模块
module ad5601spi//mode:cpol=1,cpha=0;
(
input [7:0] q,
input clk,
input rst_n,
output reg sclk,
output reg cs,
output reg sdin
);
reg [2:0] cnt;
reg[5:0]state;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)begin cnt<=0;sclk<=1;end
else if(cnt==4)begin cnt<=0;sclk<=1;end
else if(cnt<=2)begin cnt<=cnt+1;sclk<=1;end
else begin cnt<=cnt+1;sclk<=0;end
end
reg [15:0] data;
always @(posedge clk or negedge rst_n)
if(!rst_n)begin state<=0; cs=1;sdin=0;end
else begin
case(state)
0: begin if(cnt==1)begin cs<=0;data={2'b00,q[7:0],6'b000000};state<=state+1;end else begin state<=0;cs<=1;end end
1:if(cnt==2) begin sdin<=data[15];state<=state+1;end
2:if(cnt==2) begin sdin<=data[14];state<=state+1;end
3:if(cnt==2) begin sdin<=data[13];state<=state+1;end
4:if(cnt==2) begin sdin<=data[12];state<=state+1;end
5:if(cnt==2) begin sdin<=data[11];state<=state+1;end
6:if(cnt==2) begin sdin<=data[10];state<=state+1;end
7:if(cnt==2) begin sdin<=data[9];state<=state+1;end
8:if(cnt==2) begin sdin<=data[8];state<=state+1;end
9:if(cnt==2) begin sdin<=data[7];state<=state+1;end
10:if(cnt==2) begin sdin<=data[6];state<=state+1;end
11:if(cnt==2) begin sdin<=data[5];state<=state+1;end
12:if(cnt==2) begin sdin<=data[4];state<=state+1;end
13:if(cnt==2) begin sdin<=data[3];state<=state+1;end
14:if(cnt==2) begin sdin<=data[2];state<=state+1;end
15:if(cnt==2) begin sdin<=data[1];state<=state+1;end
16:if(cnt==2) begin sdin<=data[0];state<=state+1;end
17:if(cnt==2)begin state<=0;cs<=1;end
endcase
end
endmodule//spi下降沿准备数据 AD5601接受数据