打印
[FPGA]

93C46,E2PROM控制器设计

[复制链接]
662|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
feihufuture|  楼主 | 2017-5-31 14:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
测试E2PROM,即93C46

1) 93C46是一个有128字节的eeprom,可以是8位或16位的存储模式,在RTL8019AS中,用的是16位的模式,也就是总共有64个16位的存储单元.16位方式下,存储地址为0---63 .每个地址存储两个字节,低位字节在前,高位字节在后(这跟单片机的存储相反,单片机是高位在前,低位在后).
8位或者16位通过管脚硬件选择
8位时,地址位只有7位

2)写需要执行3个93c46命令:
.EWEN command写使能
.WRITE command写数据
.EWDS command禁止写

3)
   将spi时钟反相后给E2PROM,(93C46数据的读入和读出都是在时钟的上升沿,直接将控制器中使用的上升沿时钟赋值给93C46,可能会由于走线问题或者保持时间不够而造成时序混乱,比如数据比片选来的要早等等)。
   读出数据时,其datasheet已指明,数据在时钟上升沿翻转,所以控制器接收数据要用93C46时钟的反相,这样时钟上升沿正对数据稳定的中心;
   读出数据时,第一个数据固定为0,后面的8位才是有效数据


4) 代码
        `timescale 1ns / 1ps
        //////////////////////////////////////////////////////////////////////////////////
        module E2PROM_TOP(
        input clkin,
        input mi,
        input write,
        input read,
        output sck,
        output reg cs,
        output reg mo,
        output TEST
        );
        //generate spi clk
        parameter div = 40;
        reg [5:0] div_cnt = 6'b0;
        reg       spi_clk = 1'b0;
        always @ (posedge clkin)
                begin
                        if(div_cnt == div) div_cnt <= 6'b0;
                        else div_cnt <= div_cnt + 1;
                end
        always @ (posedge clkin)
                begin
                        if(div_cnt == div/2) spi_clk <= !spi_clk;
                        else if(div_cnt == div) spi_clk <= !spi_clk;
                        else spi_clk <= spi_clk;
                end
        assign sck = !spi_clk;
        //generate rst
        reg rst = 1'b0;
        reg [7:0] rst_cnt = 8'b0;
        always @ (posedge clkin)
                begin
                        if(&rst_cnt) rst_cnt <= rst_cnt;
                        else rst_cnt <= rst_cnt + 1;
                end
        always @ (posedge clkin)
                begin
                        if(&rst_cnt) rst <= 1'b0;
                        else rst <= 1'b1;
                end        
        //generate true_write
        reg [1  : 0] write_s = 2'b0;
        reg [29 : 0] write_cnt = 30'b0;
        reg          true_write = 1'b0;
        always @ (posedge spi_clk)
                begin
                        write_s <= {write_s,write};
                end        
        always @ (posedge spi_clk)
                begin
                        if(rst) write_cnt <= 30'b0;
                        else if(write_s == 2'b11) write_cnt <= write_cnt + 1;
                        else write_cnt <= 30'b0;
                end               
        //
        always @ (posedge spi_clk)
                begin
                        if(rst) true_write <= 1'b0;
                        else if(true_write) true_write <= 1'b0;
                        else if(&write_cnt[12:0]) true_write <= 1'b1;
                        else true_write <= 1'b0;
                end        
   //generate true_read
        reg [1  : 0] read_s = 2'b0;
        reg [29 : 0] read_cnt = 30'b0;
        reg          true_read = 1'b0;
        always @ (posedge spi_clk)
                begin
                        read_s <= {read_s,read};
                end        
        always @ (posedge spi_clk)
                begin
                        if(rst) read_cnt <= 30'b0;
                        else if(read_s == 2'b11) read_cnt <= read_cnt + 1;
                        else read_cnt <= 30'b0;
                end               
        //
        always @ (posedge spi_clk)
                begin
                        if(rst) true_read <= 1'b0;
                        else if(true_read) true_read <= 1'b0;
                        else if(&read_cnt[12:0]) true_read <= 1'b1;
                        else true_read <= 1'b0;
                end
        //***********************************************************
        //state
        parameter idle     = 2'b00,
                  s_write  = 2'b01,
                                 s_read   = 2'b10;
                                 
        reg [1  : 0] state = 2'b0;
        reg [9  : 0] ewen_data = 10'b100_1100000;
        reg [17 : 0] write_data = 18'b101_0111111_01011010;
        reg [9  : 0] ewds_data = 10'b100_0000000;
   reg [9  : 0] write_data_rd = 10'b110_0111111;
        reg [7  : 0] read_data;
        reg [5  : 0] wr_state_cnt = 5'b0;
        reg [4  : 0] rd_state_cnt = 5'b0;
        //state
        always @ (posedge spi_clk)
                begin
                        if(rst) state <= idle;
                        else
                                case(state)
                                idle:
                                        begin
                                        if(true_read) state <= s_read;
                                        else if(true_write) state <= s_write;
                                        end
                                s_read: state <= (rd_state_cnt == 5'd19) ? idle : s_read;
                                s_write: state <= (wr_state_cnt == 6'd50) ? idle : s_write;
                                endcase
                end
        //wr_state_cnt
        always @ (posedge spi_clk)
                begin
                        if(rst) wr_state_cnt <= 6'b0;
                        else if(state == s_write) wr_state_cnt <= wr_state_cnt + 1;
                        else wr_state_cnt <= 6'b0;
                end
        //rd_state_cnt
        always @ (posedge spi_clk)
                begin
                        if(rst) rd_state_cnt <= 5'b0;
                        else if(state == s_read) rd_state_cnt <= rd_state_cnt + 1;
                        else rd_state_cnt <= 5'b0;
                end
        //cs
        always @ (posedge spi_clk)
                begin
                        if(rst) cs <= 1'b0;
                        else if(wr_state_cnt == 6'd1) cs <= 1'b1;
                        else if(wr_state_cnt == 6'd11) cs <= 1'b0;
                        else if(wr_state_cnt == 6'd16) cs <= 1'b1;
                        else if(wr_state_cnt == 6'd34) cs <= 1'b0;
                        else if(wr_state_cnt == 6'd39) cs <= 1'b1;
                        else if(wr_state_cnt == 6'd49) cs <= 1'b0;
                        //
                        else if(rd_state_cnt == 5'd1) cs <= 1'b1;
                        else if(rd_state_cnt == 5'd19) cs <= 1'b0;
                        else cs <= cs;
                end
        //mo
        always @ (posedge spi_clk)
                begin
                        if(rst) mo <= 1'b0;
                        else if(state == s_write)
                                begin
                                case(wr_state_cnt)
                                6'd1 : mo <= ewen_data[9];
                                6'd2 : mo <= ewen_data[8];
                                6'd3 : mo <= ewen_data[7];
                                6'd4 : mo <= ewen_data[6];
                                6'd5 : mo <= ewen_data[5];
                                6'd6 : mo <= ewen_data[4];
                                6'd7 : mo <= ewen_data[3];
                                6'd8 : mo <= ewen_data[2];
                                6'd9 : mo <= ewen_data[1];
                                6'd10 : mo <= ewen_data[0];
                                //
                                6'd16 : mo <= write_data[17];
                                6'd17 : mo <= write_data[16];
                                6'd18 : mo <= write_data[15];
                                6'd19 : mo <= write_data[14];
                                6'd20 : mo <= write_data[13];
                                6'd21 : mo <= write_data[12];
                                6'd22 : mo <= write_data[11];
                                6'd23 : mo <= write_data[10];
                                6'd24 : mo <= write_data[9];
                                6'd25 : mo <= write_data[8];
                                6'd26 : mo <= write_data[7];
                                6'd27 : mo <= write_data[6];
                                6'd28 : mo <= write_data[5];
                                6'd29 : mo <= write_data[4];
                                6'd30 : mo <= write_data[3];
                                6'd31 : mo <= write_data[2];
                                6'd32 : mo <= write_data[1];
                                6'd33 : mo <= write_data[0];
                                //
                                6'd39 : mo <= ewds_data[9];
                                6'd40 : mo <= ewds_data[8];
                                6'd41 : mo <= ewds_data[7];
                                6'd42 : mo <= ewds_data[6];
                                6'd43 : mo <= ewds_data[5];
                                6'd44 : mo <= ewds_data[4];
                                6'd45 : mo <= ewds_data[3];
                                6'd46 : mo <= ewds_data[2];
                                6'd47 : mo <= ewds_data[1];
                                6'd48 : mo <= ewds_data[0];
                                //
                                default: mo <= 1'b0;
                                endcase
                                end
                        else if(state == s_read)
                                begin
                                case(rd_state_cnt)
                                5'd1 : mo <= write_data_rd[9];
                                5'd2 : mo <= write_data_rd[8];
                                5'd3 : mo <= write_data_rd[7];
                                5'd4 : mo <= write_data_rd[6];
                                5'd5 : mo <= write_data_rd[5];
                                5'd6 : mo <= write_data_rd[4];
                                5'd7 : mo <= write_data_rd[3];
                                5'd8 : mo <= write_data_rd[2];
                                5'd9 : mo <= write_data_rd[1];
                                5'd10 : mo <= write_data_rd[0];
                                endcase
                                end
                end        
   //mi
        always @ (posedge spi_clk)
                begin
                        if(rst) read_data <= 8'b0;
                        else if(state == s_read)
                                begin
                                case(rd_state_cnt)
                                5'd12 : read_data[7] <= mi;
                                5'd13 : read_data[6] <= mi;
                                5'd14 : read_data[5] <= mi;
                                5'd15 : read_data[4] <= mi;
                                5'd16 : read_data[3] <= mi;
                                5'd17 : read_data[2] <= mi;
                                5'd18 : read_data[1] <= mi;
                                5'd19 : read_data[0] <= mi;
                                endcase
                                end
                end
        assign TEST = (read_data[7:0] == write_data[7:0]) ? 1'b1 : 1'b0;
        
        endmodule

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:WX:feihu612 免费合作开发ECAT主从站

171

主题

1027

帖子

97

粉丝