note
实现功能:按键按一次加一写入数据,ila读出加的数据
所用芯片:EEPROM24LC04 的设备地址为 0xA0
所用I2C总线包含两根总线:I2C_SCL和I2C_SDA
pullup();上拉电阻
空闲状态:SDA,SCL都为高
起始位SCL为高时,SDA出现一个下降沿
停止位:SCL为高时,SDA出现一个上升沿
数据位传送:SCL为低时,SDA数据发生变化
应答信号:ACK=0 NACK=1
三态门
输入时,输出使能关闭,A无法传到AB,AB传到B
输出时,输出使能打开,A传到AB、B
code
按键消抖模块
`timescale 1ns / 1ns
module ax_debounce(input clk, input rst, input button_in,output reg button_posedge,output reg button_negedge,output reg button_out);
parameter NUMBER=997;//20ms所需要的计数值20ms/20ns需要二十位宽
//仿真用20us,DFF1和DFF2比较加计数值清零,延时了三个时钟周期
reg [19: 0] q_reg;//计数器
reg [19: 0] q_next;
reg DFF1, DFF2;//DFF1接收button_in数据,再赋值给DFF2,比较二者判断电平变化
wire q_add;//控制计数值是否往上加
wire q_reset;
reg button_out_d0;
assign q_reset = (DFF1^DFF2);//前后两个电平不同重置计数器
assign q_add = ~(q_reg == NUMBER); // 计数到20ms置0,是1且q_reset为0时计数器加一
//计数器的累加
always @ ( q_reset, q_add, q_reg)begincase( {q_reset , q_add})2'b00:q_next <= q_reg;2'b01:q_next <= q_reg + 1;default:q_next <= { 20 {1'b0} };endcase
end
//判断上升沿和下降沿
always @ ( posedge clk or posedge rst)beginif(rst) beginbutton_out_d0 <= 1'b1;button_posedge <= 1'b0;button_negedge <= 1'b0;endelse beginbutton_out_d0 <= button_out;button_posedge <= ~button_out_d0 & button_out;button_negedge <= button_out_d0 & ~button_out;end
end
//输入值与计数值的更新
always @ ( posedge clk or posedge rst)beginif(rst)beginDFF1 <= 1'b0;DFF2 <= 1'b0;q_reg <= { 20 {1'b0} };endelse beginDFF1 <= button_in;DFF2 <= DFF1;q_reg <= q_next;end
end
//输出
always @ ( posedge clk or posedge rst)beginif(rst)button_out <= 1'b1;else if(q_reg == NUMBER)button_out <= DFF2;elsebutton_out <= button_out;
end
endmodule
EEPROM模块
在这里插入代码片
tb
按键消抖
`timescale 1ns / 1ns
module tb();reg clk; reg rst; reg button_in;wire button_posedge;wire button_negedge;wire button_out;
ax_debounce ax_debounce1(clk, rst, button_in,button_posedge,button_negedge,button_out);initial clk=1;always #10 clk=~clk;initial beginrst=1;button_in=0;#401;rst=0;button_in=1;#40;button_in=0;#40;button_in=1;#40;button_in=0;#20000;button_in=1;#40;button_in=0;#40;button_in=1;#20020;$stop;end
endmodule
`timescale 1ns/1ns
module i2c_eeprom_test_tb;
reg sys_clk;
reg rst_n;
reg key;
wire SCL;
wire SDA;
wire [3:0] led ;
initial
beginsys_clk = 1'b0;rst_n = 1'b0;key = 1'b1;#100 rst_n = 1'b1;#250 key = 1'b0;#500000 key = 1'b1;#500000 key = 1'b0;#500000 key = 1'b1;
end
always#10 sys_clk = ~sys_clk;//50Mhz
pullup p1(SDA);
pullup p2(SCL);
i2c_eeprom_test dut(.sys_clk (sys_clk),.rst_n (rst_n),.key (key),.i2c_sda (SDA),.i2c_scl (SCL),.led (led)
);
M24AA02 memory
(.A0(1'b0), .A1(1'b0), .A2(1'b0), .WP(1'b0), .SDA(SDA), .SCL(SCL), .RESET(1'b0));
endmodule
sim
ps
之前学的按键消抖看了好久,每一个小实验真的都可以反复做多次,基础打牢很重要。