夏宇闻那本书的EEPROM程序 感觉程序根本就不能进入读操...

2019-07-16 01:01发布

`timescale 1ns/1ns
`define timeslice 100
module EEPROM(scl,sda);
input scl;//串行时钟线
inout sda;//串行数据线
reg out_flag;//sda数据输出的控制信号
reg[7:0] memory[2047:0];
reg[10:0] address;
reg[7:0] memory_buf;
reg[7:0] sda_buf;//sda数据输出寄存器
reg[7:0] shift;//sda数据输入寄存器
reg[7:0] addr_byte;//eeprom存储单元地址寄存器
reg[7:0] ctrl_byte;//控制字寄存器
reg[1:0] 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

assign sda=(out_flag==1)?sda_buf[7]:1'bz;

//寄存器和存储器初始化
initial
begin
addr_byte=0;
ctrl_byte=0;
out_flag=0;
sda_buf=0;
State=2'b00;
memory_buf=0;
address=0;
shift=0;
for(i=0;i<=2047;i=i+1)
        memory[i]=0;
end

//启动信号
always @(negedge sda)
if(scl==1)
        begin
        State=State+1;
        if(State==2'b11)
                disable write_to_eeprom;
end

//主状态机
always @(posedge sda)
if(scl==1)
        stop_W_R;
else
        begin
        casex(State)
        2'b01:
        begin
        read_in;
        if(ctrl_byte==w7||ctrl_byte==w6||ctrl_byte==w5||ctrl_byte==w4||
           ctrl_byte==w3||ctrl_byte==w2||ctrl_byte==w1||ctrl_byte==w0)
                begin
                State=2'b10;
                write_to_eeprm;//写操作
                end
        else
                State=2'b00;
        end
        2'b11:
        read_from_eeprm;//读操作
        default:
        State=2'b00;
        endcase
end//主状态机结束

//操作停止
task stop_W_R;
        begin
        State=2'b00;//状态返回为初始状态
        addr_byte=0;
        ctrl_byte=0;
        out_flag=0;
        sda_buf=0;
        end
endtask

//读进控制字和存储单元地址
task read_in;
        begin
        shift_in(ctrl_byte);
        shift_in(addr_byte);
        end
endtask

//EEPROM的写操作
task write_to_eeprm;
        begin
        shift_in(memory_buf);
        address={ctrl_byte[3:1],addr_byte};
        memory[address]=memory_buf;
        $display("eeprm--memory[%0h]=%0h",address,memory[address]);
        State=2'b00;//回到0状态
        end
endtask

//EEPROM的读操作
task read_from_eeprm;
        begin
        shift_in(ctrl_byte);
        if(ctrl_byte==r7||ctrl_byte==r6||ctrl_byte==r5||ctrl_byte==r4||
           ctrl_byte==r3||ctrl_byte==r2||ctrl_byte==r1||ctrl_byte==r0)
                begin
                address={ctrl_byte[3:1],addr_byte};
                sda_buf=memory[address];
                shift_out;
                State=2'b00;
                end
        end
endtask

//SDA数据线上的数据存入寄存器,数据在SCL的高电平有效
task shif_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)
                begin
                #`timeslice;
                out_flag=1;//应答信号输出
                sda_buf=0;
                end
        @(negedge scl)
                #`timeslice out_flag=0;
        end
endtask

//EEPROM存储器中的数据通过SDA数据线输出,数据在SCL低电平时变化
task shift_out;
        begin
        out_flag=1;
        for(i=6;i>=0;i=i-1)
                begin
                @(negedge scl);
                #`timeslice;
                sda_buf=sda_buf<<1;
                end
        @(negedge scl) #`timeslice sda_buf[7]=1;//非应答信号输出
        @(negedge scl) #`timeslice out_flag=0;
        end
endtask
endmodule
//eeprom.v文件结束

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。