📄 eeprm.v
字号:
//***********************************************************************************
//*** eeprm is a verilog HDL behavioral model for AT24C02/4/8/16
`define timeslice2 100
module eeprm (a0, a1, a2, scl, test, sda) ;
input a0 ;
input a1 ;
input a2 ;
input scl ;
input test ;
inout sda ;
reg[7:0] memory[2047:0],memory_buf,sda_buf;
//16k bits memory means 2048 bytes
reg[7:0] shift_buf,addr_word,cmm_word;
reg out_flag;
reg[1:0] W_R_state;
integer i;
//----------------------------------------------------------------------------------
parameter r7 = 8'b10101111, w7 = 8'b10101110, //main7
r6 = 8'b10101101, w6 = 8'b10101100, //main6
r5 = 8'b10101011, w5 = 8'b10101010, //main5
r4 = 8'b10101001, w4 = 8'b10101000, //main4
r3 = 8'b10100111, w3 = 8'b10100110, //main3
r2 = 8'b10100101, w2 = 8'b10100100, //main2
r1 = 8'b10100011, w1 = 8'b10100010, //main1
r0 = 8'b10100001, w0 = 8'b10100000; //main0
//----------------------------------------------------------------------------------
initial
begin
addr_word = 0;
cmm_word = 0;
out_flag = 0;
sda_buf = 0;
W_R_state = 2'b00;
memory_buf = 0;
for (i = 0; i <= 2047; i = i + 1)
memory[i] = 0;
end
//----------------------------------------------------------------------------------
assign sda = (out_flag == 1)? sda_buf[7] : 1'bz;
//*** out_flag is used to notify sda is linked to sda_buf
//*** out_flag == 0 means sda_buf is seperated form sda.
//----------------------------------------------------------------------------------
//**********************************************************************************
//**** start receiving
//**********************************************************************************
always @(negedge sda)
if (scl == 1)
begin
W_R_state = W_R_state + 1;
if (W_R_state == 2'b11)
begin
disable work2;
end
end
//**********************************************************************************
//**** main state machine
//**********************************************************************************
always @(posedge sda)
if (scl == 1)
stop_W_R;
else
begin
casex(W_R_state)
2'b01:
begin
work1;
if (cmm_word == w7 || cmm_word == w6 || cmm_word == w5 || cmm_word == w4
|| cmm_word == w3 || cmm_word == w2 || cmm_word == w1 || cmm_word == w0)
begin
W_R_state = 2'b10;
work2;
end
else
W_R_state = 2'b00;
end
2'b11: work3;
default: W_R_state = 2'b00;
endcase
end
//*********************************************************************************
//**** stop receiving
//*********************************************************************************
task stop_W_R;
begin
W_R_state = 2'b00;
addr_word = 0;
cmm_word = 0;
out_flag = 0;
sda_buf = 0;
end
endtask
//*********************************************************************************
//*** Task work1 is used to do the real work of analysis of sda bit stream command,
//*** and according to the command words int bit stream to decide what action it
//*** should take, writing into memory or reading out from memory. Then the real
//*** work of bit by bit storing into memory or bit by bit reading out from memory
//*** begins and continues, according to the command word it received.
//*********************************************************************************
//---------------------------------------------------------------------------------
task work1;
begin
shift_in(cmm_word);
shift_in(addr_word);
end
endtask
//----------------------------------------------------------------------------------
task work2;
begin
shift_in(memory_buf);
memory[cmm_word[3:1] * 256 + addr_word] = memory_buf;
W_R_state = 2'b00;
end
endtask
//-----------------------------------------------------------------------------------
task work3;
begin
shift_in(cmm_word);
if (cmm_word == r7 || cmm_word == r6 || cmm_word == r5 || cmm_word == r4
|| cmm_word == r3 || cmm_word == r2 || cmm_word == r1 || cmm_word == r0)
begin
sda_buf = memory[cmm_word[3:1] * 256 + addr_word];
shift_out;
W_R_state = 2'b00;
end
end
endtask
//***********************************************************************************
//*** Task shift_in is used to get the sda serial bits into shift[7:0],
//*** one bit every one scl posedge, when serial bits are required to
//*** be stored into EEPROM.
//***********************************************************************************
task shift_in;
output[7:0] shift;
begin
@(posedge scl) shift[7] = sda;
@(posedge scl) shift[6] = sda;
@(posedge scl) shift[5] = sda;
@(posedge scl) shift[4] = sda;
@(posedge scl) shift[3] = sda;
@(posedge scl) shift[2] = sda;
@(posedge scl) shift[1] = sda;
@(posedge scl) shift[0] = sda;
@(negedge scl) //Send out acknowledge
begin
#`timeslice2 out_flag = 1; //link sda_buf to sda ready to send serial data
sda_buf = 0; //make sda low to send an acknowledge
end
@(negedge scl)
#`timeslice2 out_flag = 0; //delay half scl2 separate sda_buf with sda
end
endtask
//***********************************************************************************
//*** Task shift_out is used to send out the byte, sda_buf[7:0] to sda,
//*** one bit every one scl negedge, when the byte stored in memory is
//*** required. out_flag is used to link sda with the MSB of sda_buf[7:0]
//***********************************************************************************
task shift_out;
begin
out_flag = 1;
for (i = 6; i >= 0; i = i - 1)
@(negedge scl) #`timeslice2 sda_buf = sda_buf << 1;
@(negedge scl)
#`timeslice2 sda_buf[7] = 1; //no ack
@(negedge scl)
#`timeslice2 out_flag = 0; //seprate sda_buf with sda
end
endtask
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -