📄 at24c02.v
字号:
//**********************************************************************//**********************************************************************`timescale 1ns / 10 ps//05-01-2002 Bryce Morgan//AT24C02 Verilog Model //This model was developed to accurately describe the functional behavior//of the Atmel Serial EEPROM Product AT24C02.module AT24C02( sda, scl, wp); inout sda; // Serial datainput scl; // Serial clockinput wp; // Write protectionparameter DEVICE = "AT24C02"; // Device nameparameter Device_Address = 7'b1010000; // Device Addressparameter MEM_SIZE = 256 ; // Number of bytes in memoryparameter PAGE_SIZE = 8 ; // Number of bytes in each pageparameter BYTE_SIZE = 8 ; // Number of bits in a byteparameter ADDR_SIZE = 8 ; // number of address bitsparameter ADDR_REG_SIZE = 8 ; // Size of address register parameter Time_out_for_Write = 40_000; // Shorten for test//parameter Time_out_for_Write = 10_000_000; // Scaled to 10 ms.parameter tAA= 550; // Worst-case Clock Low to Data Out Valid//***************************************************************************//***************************************************************************// Memory Boundaries //***************************************************************************//***************************************************************************reg [(ADDR_REG_SIZE - 1):0] addr_reg ; // 8-bit address register.reg [(BYTE_SIZE - 1):0] memory[(MEM_SIZE-1):0] ; //Main Memoryreg [BYTE_SIZE-1: 0] S_Byte_Shft_Reg;reg load_address_bit, M_ACK;reg ld_S_Byte_Shft_Reg;reg ld_addr_reg_LSB_byte;reg shift_in;reg shift_out;parameter send = 1, receive = 0;parameter [31:0] sending = "send";parameter [31:0] receiving = "recv";reg [2:0] state_recv, next_state_recv;reg [2:0] state_send, next_state_send;wire sda_out;reg S_send_rcvb;reg Addr_Done;reg S_ACK;//reg Valid_Address_and_A1_flg;reg Valid_Device_Address;//************************************************************************//************************// Slave bus controls *************************//************************************************************************reg NO_ACK_flag; // Flag indicating No_ACK from masterreg TOFG; // Time out flagtri sda = (S_send_rcvb == send)? ((S_ACK == 0)? sda_out: 1'b0): 1'bz;tri sda_in = (S_send_rcvb == receive)? sda : 1'bz;wire [31:0] receiver = (S_send_rcvb == send)? sending : ((S_send_rcvb == receive)) ? receiving : 32'bx; event S_START_condition;event S_STOP_condition;event incr_addr_reg;reg S_START, S_STOP;//************************************************************************//********************* S_START and S_STOP conditions ********************//************************************************************************always @ (negedge sda_in) if(scl == 1)begin -> S_START_condition; $display("************************************** START condition detected"); S_START = 1; S_STOP = 0; Valid_Device_Address = 0; @ (posedge scl) S_START = 0; endalways @ (posedge sda_in) if(scl == 1) begin -> S_STOP_condition;S_STOP = 1; Valid_Device_Address = 0;disable MACHINE_LOOP.Main_Loop ; // added by xujun$display ("*************************************** STOP condition detected");end//************************************************************************//************************ Memory Initialization *************************//************************************************************************integer k;initial for (k = 0; k<= MEM_SIZE-1; k = k+1) beginmemory[k] = 8'hFF;end//initial for (k = 0; k<= MEM_SIZE-1; k = k+1) begin //modified by zxc//memory[k] = k;//endwire [7:0] mem_byte = memory[addr_reg[7:0]]; //@@ Used for debug to watch memory//************************************************************************//*************************** Address Register Controls ******************//************************************************************************always @ (posedge scl) if (ld_addr_reg_LSB_byte == 1) //???? addr_reg[ADDR_REG_SIZE-1:0] <= S_Byte_Shft_Reg[7:0]; // else if (ld_addr_reg_LSB_byte == 1) //addr_reg[(ADDR_SIZE-1)/2 -1 : 0] <= S_Byte_Shft_Reg;// Increment after READ always @ (incr_addr_reg) addr_reg <= addr_reg +1; //*************************************************************************//************************** Shift Register ************************//*************************************************************************assign sda_out = S_Byte_Shft_Reg [BYTE_SIZE-1];always @(posedge scl)if (shift_in == 1) S_Byte_Shft_Reg <= { S_Byte_Shft_Reg [BYTE_SIZE-2:0], sda_in };else if (shift_out == 1) @(negedge scl) S_Byte_Shft_Reg <= S_Byte_Shft_Reg << 1; //switching on every positive_edge else if (ld_S_Byte_Shft_Reg == 1) S_Byte_Shft_Reg <= memory[addr_reg[7:0]]; //*************************************************************************//*********************** Read/Write State Machine ************************//*************************************************************************always begin : MACHINE_LOOP Power_up_initialization; forever begin : Main_Loop $display("Begin Main Loop"); S_send_rcvb = receive; $display ("Waiting for START_condition"); @ (S_START_condition) begin :Data_Transmission $display("Data_Transmission"); Get_a_Byte; Parse_the_Address_Byte_and_Read_or_Write_if_Valid; end // Data_Transmission end // Main_Loop end // Machine_Loop //*************************************************************************//*************************************************************************task Get_a_Byte; begin NO_ACK_flag = 0; shift_in = 1; repeat (8) begin @ (posedge scl); end endendtasktask Parse_the_Address_Byte_and_Read_or_Write_if_Valid; begin @ (negedge scl) shift_in = 0; NO_ACK_flag = 0; Check_for_Valid_Device_Address; if (Valid_Device_Address) begin: Device_Address_Match $display ("Device Address Match"); case (S_Byte_Shft_Reg[0]) 0: Write_or_Dummy_Write_with_Random_Read; 1: Current_Address_and_Sequential_Read; default: $display("Invalid device address word received"); endcase end //Device_Address_Match endendtasktask Check_for_Valid_Device_Address; begin if (S_Byte_Shft_Reg[BYTE_SIZE-1: BYTE_SIZE-7] == Device_Address) Valid_Device_Address = 1; endendtasktask Write_or_Dummy_Write_with_Random_Read; begin :Write_Sequence if (wp == 1) begin $display ("Chip is write-protected"); disable Write_Sequence; end else begin: Chip_not_write_protected $display("***************************************** Begin Write Sequence"); Set_Flags_and_Get_Address_Bytes_and_ACK_to_Master; shift_in = 1; $display("Address bytes are loaded"); @ (posedge scl); // MSB is saved $display("First clock after address bytes are loaded"); @ (posedge S_START or posedge scl) if (S_START ==1) begin $display("Dummywrite detected - this is the device address byte"); Get_a_Byte; Begin_a_Read_Sequence; end else begin: Byte_or_Page_Write $display("Write sequence"); Get_Remainder_of_Byte; ACK_and_write_a_Byte; addr_reg[7:0] <= addr_reg[7:0] +1; $display("Increment the address register"); Execute_page_Write; $display ("*******************************End of page write"); #Time_out_for_Write TOFG = 0; end // Byte_or_Page_Write end // Chip_not_write_protected end // Write_Sequenceendtasktask ACK_and_write_a_Byte; begin $display ("ACK and write a byte"); @ (negedge scl) S_ACK = 1; shift_in = 0; S_send_rcvb = send; @ (posedge scl) memory[addr_reg[7:0]] <= S_Byte_Shft_Reg[7:0]; @ (negedge scl) S_ACK = 0; shift_in = 1; S_send_rcvb = receive; endendtasktask Get_Remainder_of_Byte; begin repeat (6) begin @ (posedge scl); end endendtasktask Set_Flags_and_Get_Address_Bytes_and_ACK_to_Master; begin S_send_rcvb = send; S_ACK = 1; // Send ACK to master @(negedge scl) S_ACK = 0; shift_in = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -