二線制I2C CMOS串行EEPROM續(xù)

本篇文章主要介紹一下EEPROM讀寫器件的設(shè)計思路诲侮,以及未來測試此器件搭建的測試平臺镀虐。

1、串行EEPROM讀寫器件

我們要設(shè)計一個串行EEPROM讀寫器件浆西,這要求我們設(shè)計出能夠綜合的Verilog HDL代碼粉私。所謂串行EEPROM讀寫器件就是指將我們平常輸入信號的輸入習(xí)慣產(chǎn)生符合I2C串行總線的數(shù)據(jù)。我們給此模塊命名為EEPROM_WR近零。
要搭建測試平臺才能夠?qū)υO(shè)計進(jìn)行驗證诺核,這里搭建的測試平臺,只用做行為級描述久信,不一定符合可綜合的設(shè)計要求窖杀。搭建測試平臺需要信號輸入模塊signal和EEPROM模塊。


EEPROM讀寫電路及其測試電路.png

下面就這三個模塊做一一的詳細(xì)介紹

EEPROM

我們理想的EEPROM數(shù)據(jù)的讀寫規(guī)則就是按照I2C總線給出的規(guī)則進(jìn)行裙士。在這里入客,我們先貼出相應(yīng)的代碼,然后進(jìn)行分析腿椎。

`timescale 1ns/1ns
`define timeslice 100
 module EEPROM(scl,sda);
 input scl;
 inout sda;

 reg out_flag;
 reg [7:0] memory [2047:0];
 reg [10:0] address;
 reg [7:0] memory_buf;
 reg [7:0] sda_buf;
 reg [7:0] shift;
 reg [7:0] addr_byte;
 reg [7:0] ctrl_byte;
 reg [1:0] state;
 integer i;

  parameter r7=8'b10101111, w7=8'b10101110,
        r6=8'b10101101, w6=8'b10101100,
        r5=8'b10101011, w5=8'b10101010,
        r4=8'b10101001, w4=8'b10101000,
        r3=8'b10100111, w3=8'b10100110,
        r2=8'b10100101, w2=8'b10100100,
        r1=8'b10100011, w1=8'b10100010,
        r0=8'b10100001, w0=8'b10100000;

  assign sda=(out_flag==1)? sda_buf[7]:1'bz; //sda線上作為輸出

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)  //scl為高電平桌硫,sda的下降沿,表示啟動信號
    begin
    if(scl==1)
     begin
      state=state+1;
      if(state==2'b11)   //讀操作的另一次啟動信號啃炸,此時已經(jīng)完成了從sda總線上讀控制字和讀地址的操作铆隘。
      disable write_to_EEPROM;
  end
 end

  always@(posedge sda) //僅僅跟隨在啟動信號之后的觸發(fā)條件,因為控制字是1010XXXX南用,所以sda的上升沿就跳入此模塊膀钠。
  begin
  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;    //從sda上讀取寫控制字和地址
              write_to_EEPROM;  //將sda上的數(shù)據(jù)寫如EEPROM.
            end
          else
            state=2'b00;
          end
     2'b11: read_from_EEPROM; // 寫控制字,讀數(shù)據(jù)
     default: state=2'b00;
   endcase
 end
end

task shift_in; //總共消耗9個scl周期裹虫,前8個用于讀數(shù)據(jù)肿嘲,將sda讀出,最后一個用于應(yīng)答位的產(chǎn)生筑公,sda被驅(qū)動賦值雳窟。
  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) //最后這兩個scl的下降沿是輸出sda,用于應(yīng)答信號匣屡,詳細(xì)可參考波形1.
   begin
    #`timeslice
    out_flag=1;
    sda_buf=0; // 應(yīng)答位0.
    end
 @(negedge scl) 
   begin
    #`timeslice
     out_flag=0;
    end 
 end
  endtask

 task read_in;
 begin
   shift_in(ctrl_byte);
   shift_in(addr_byte);
 end
 endtask

 task shift_out;//將sda_buf上的數(shù)據(jù)寫到總線上去涩拙,共消耗9個scl時鐘周期,其中前8個時鐘周期是將sdf_buf的內(nèi)容賦值到sda中去耸采。
 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
 
task stop_W_R;
  begin
    state=2'b00;
    addr_byte=0;
    ctrl_byte=0;
    out_flag=0;
    sda_buf=0;
  end
endtask
  

task write_to_EEPROM;  //將sda上的數(shù)據(jù)寫入到EEPROM指定的地址中。
    begin
    shift_in(memory_buf);
    address={ctrl_byte[3:1],addr_byte};
    memory[address]=memory_buf;
    $display("EEPROM-----memory[%0h]=%0h",address,memory[address]);
    state=2'b00;
    end
endtask

task read_from_EEPROM; //將EEPROM中指定地址的值放入sda總線上工育。
  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
endmodule
寫操作.png

讀操作.png
EEPROM_WR

EEPROM讀寫器件我們要求設(shè)計成可綜合的設(shè)計風(fēng)格代碼虾宇,它接受來自信號源模型產(chǎn)生的讀信號、寫信號如绸、并行地址信號和并行數(shù)據(jù)信號嘱朽,并把它們轉(zhuǎn)換成相應(yīng)的串行信號發(fā)送到EEPROM的行為模型中去旭贬。
這部分主要由兩部分組成:一部分是開關(guān)組合電路,另一部分是控制時序電路搪泳。


EEPROM讀寫器的結(jié)構(gòu).png

電路上的同步采用有限狀態(tài)機(jī)的設(shè)計方法實現(xiàn)稀轨,程序上則采用的是一個有限狀態(tài)機(jī)的嵌套結(jié)構(gòu),由主狀態(tài)機(jī)和從狀態(tài)機(jī)通過由控制總線啟動的總線在不同的輸入信號下構(gòu)成不同功能的較為復(fù)雜的有限狀態(tài)機(jī)岸军,這個有限狀態(tài)機(jī)只有唯一的驅(qū)動時鐘clk奋刽。
EEPROM讀寫器的狀態(tài)機(jī).png

寫狀態(tài)由5個狀態(tài)完成,讀狀態(tài)由7個狀態(tài)完成艰赞。在本代碼中佣谐,我們選擇了利用獨熱碼對狀態(tài)機(jī)進(jìn)行編碼,若改變狀態(tài)編碼方妖,只需要改變程序中的parameter定義即可狭魂。
下面就代碼結(jié)合波形,我給大家做一下簡要的分析党觅。
本模塊以狀態(tài)轉(zhuǎn)移為框架雌澄,讀寫過程分為三步開始、讀/寫杯瞻、結(jié)束镐牺。在讀寫過程中,涉及到串聯(lián)轉(zhuǎn)并聯(lián)又兵、并聯(lián)轉(zhuǎn)串聯(lián)的任務(wù)任柜。能夠清楚地掌握何時進(jìn)行開關(guān)的打開和關(guān)閉是設(shè)計成功的關(guān)鍵步驟。
module EEPROM_WR(
             sda,
             scl,
             ack,
             reset,
             clk,
             wr,
             rd,
             addr,
             data
             );
input clk,reset,wr,rd;
input[10:0]addr;
output scl,ack;
inout sda;
inout[7:0]data;

 reg scl;
 reg ack;
 reg wf,rf;
 reg ack_f;
 reg[1:0] head_buf;
 reg[1:0] stop_buf;
 reg[7:0] storage_buf;
 reg[8:0] w_state;
 reg[9:0] r_state;
 reg[2:0] head_state;
 reg[2:0] stop_state;
 reg[10:0] main_state;
 reg[7:0] data_from_sda;
 reg link_sda,link_read,link_write,link_head,link_stop;
 wire sda1,sda2,sda3,sda4;

  assign sda1=(link_head==1)? head_buf[1] : 1'b0;  //開始
  assign sda2=(link_stop==1)? stop_buf[1] : 1'b0;  //結(jié)束
  assign sda3=(link_write==1)? storage_buf[7] : 1'b0;//數(shù)據(jù)的輸出
  assign sda4=sda1|sda2|sda3; //sda線上的輸出數(shù)據(jù)
  assign sda=(link_sda==1)? sda4 : 1'bz;
  assign data=(link_read==1'b1)? data_from_sda : 8'hzz;

 parameter idle        = 11'b00000000001,   //主狀態(tài)機(jī)
        ready       = 11'b00000000010,
        write_start = 11'b00000000100,
        ctrl_write  = 11'b00000001000,
        addr_write  = 11'b00000010000,
        data_write  = 11'b00000100000,
        read_start  = 11'b00001000000,
        ctrl_read   = 11'b00010000000,
        data_read   = 11'b00100000000,
        stop        = 11'b01000000000,
        ackn        = 11'b10000000000;
        
 parameter data_to_sda_7  = 9'b000000001,   //并聯(lián)轉(zhuǎn)串聯(lián)
        data_to_sda_6  = 9'b000000010,
        data_to_sda_5  = 9'b000000100,
        data_to_sda_4  = 9'b000001000,
        data_to_sda_3  = 9'b000010000,
        data_to_sda_2  = 9'b000100000,
        data_to_sda_1  = 9'b001000000,
        data_to_sda_0  = 9'b010000000,
        data_to_sda_end = 9'b100000000;
        
parameter sda_to_data_begin = 10'b0000000001,   //串聯(lián)轉(zhuǎn)并聯(lián)
       sda_to_data_7     = 10'b0000000010,
       sda_to_data_6     = 10'b0000000100,
       sda_to_data_5     = 10'b0000001000,
       sda_to_data_4     = 10'b0000010000,
       sda_to_data_3     = 10'b0000100000,
       sda_to_data_2     = 10'b0001000000,
       sda_to_data_1     = 10'b0010000000,
       sda_to_data_0     = 10'b0100000000,
       sda_to_data_end   = 10'b1000000000; 
       
parameter head_begin = 3'b001,   //開始狀態(tài)
        head_bit   = 3'b010,
        head_end   = 3'b100;
        
 parameter stop_begin = 3'b001,   // 結(jié)束狀態(tài)
        stop_bit   = 3'b010,
        stop_end   = 3'b100;
        

task serial_to_perallel;                          
begin
  casex(r_state)
    sda_to_data_begin: begin
                       r_state <= sda_to_data_7;
                       link_sda<=1'b0;
                       end
    sda_to_data_7    : if(scl)
                        begin
                          data_from_sda[7]<=sda;
                          r_state<=sda_to_data_6;
                        end
                       else
                          r_state<=sda_to_data_7;
    sda_to_data_6    : if(scl)
                        begin
                          data_from_sda[6]<=sda;
                          r_state<=sda_to_data_5;
                        end
                       else
                          r_state<=sda_to_data_6;
    sda_to_data_5    : if(scl)
                        begin
                          data_from_sda[5]<=sda;
                          r_state<=sda_to_data_4;
                        end
                       else
                          r_state<=sda_to_data_5;
    sda_to_data_4    : if(scl)
                        begin
                          data_from_sda[4]<=sda;
                          r_state<=sda_to_data_3;
                        end
                       else
                          r_state<=sda_to_data_4;
    sda_to_data_3    : if(scl)
                        begin
                          data_from_sda[3]<=sda;
                          r_state<=sda_to_data_2;
                        end
                       else
                          r_state<=sda_to_data_3;
    sda_to_data_2    : if(scl)
                        begin
                          data_from_sda[2]<=sda;
                          r_state<=sda_to_data_1;
                        end
                       else
                          r_state<=sda_to_data_2;
   sda_to_data_1    : if(scl)
                        begin
                          data_from_sda[1]<=sda;
                          r_state<=sda_to_data_0;
                        end
                       else
                          r_state<=sda_to_data_1;
  sda_to_data_0    : if(scl)
                        begin
                          data_from_sda[0]<=sda;
                          r_state<=sda_to_data_end;
                        end
                       else
                          r_state<=sda_to_data_0;
sda_to_data_end    : if(scl)
                        begin
                         link_read<=1'b1;
                        // link_sda<=1'b0;
                         ack_f<=1'b1;
                         r_state<=sda_to_data_7;
                        end
                      else
                        r_state<=sda_to_data_end;
                         
  /* default:  begin
             link_read<=1'b0;
             r_state<=sda_to_data_7;
           end*/
         endcase
       end
endtask


task perallel_to_serial;                   
  begin
    casex(w_state)
      data_to_sda_7: if(!scl)
                       begin
                         link_sda<=1'b1;
                         link_write<=1'b1;
                         w_state<=data_to_sda_6;
                       end
                     else
                         w_state<=data_to_sda_7;                  
        data_to_sda_6: if(!scl)
                       begin
                         link_sda<=1'b1;
                         link_write<=1'b1;
                         storage_buf<=storage_buf<<1;
                         w_state<=data_to_sda_5;
                       end
                     else
                         w_state<=data_to_sda_6; 
       data_to_sda_5: if(!scl)
                       begin
                         storage_buf<=storage_buf<<1;
                         w_state<=data_to_sda_4;
                       end
                     else
                         w_state<=data_to_sda_5;                
       data_to_sda_4: if(!scl)
                       begin
                         storage_buf<=storage_buf<<1;
                         w_state<=data_to_sda_3;
                       end
                     else
                         w_state<=data_to_sda_4; 
       data_to_sda_3: if(!scl)
                       begin
                         storage_buf<=storage_buf<<1;
                         w_state<=data_to_sda_2;
                       end
                     else
                         w_state<=data_to_sda_3; 
       data_to_sda_2: if(!scl)
                       begin
                         storage_buf<=storage_buf<<1;
                         w_state<=data_to_sda_1;
                       end
                     else
                         w_state<=data_to_sda_2; 
        data_to_sda_1: if(!scl)
                       begin
                         storage_buf<=storage_buf<<1;
                         w_state<=data_to_sda_0;
                       end
                     else
                         w_state<=data_to_sda_1; 
        data_to_sda_0: if(!scl)
                       begin
                         storage_buf<=storage_buf<<1;
                         w_state<=data_to_sda_end;
                       end
                     else
                         w_state<=data_to_sda_0; 
        data_to_sda_end: if(!scl)
                       begin
                         ack_f<=1'b1;
                         link_sda<=1'b0;
                         link_write<=1'b0;
                       end
                     //else
                       //  w_state<=data_to_sda_end;          
                 endcase
        end
  endtask
                     
    
   task head; 
  begin
    casex(head_state)
    head_begin:if(!scl)
                 begin
                   link_write<=1'b0;
                   link_sda<=1'b1;
                   link_head<=1'b1;
                   head_state<=head_bit;
                 end
               else
                 head_state<=head_begin;
   head_bit:if(scl)
                 begin
                   ack_f<=1'b1;
                   head_buf<=head_buf<<1;
                   head_state<=head_end;
                 end
               else
                 head_state<=head_bit;
   head_end:if(!scl)
              begin
              link_write<=1'b0;
              link_head<=1'b0;
              end 
              else
              head_state<=head_end;  
            endcase
          end
      endtask    
              
              
task stop_1; 
  begin
    casex(stop_state)
    stop_begin: if(!scl)
                   begin
                   link_sda<=1'b1;
                   link_stop<=1'b1;
                   //link_write<=1'b0;
                   stop_state<=stop_bit;
                   end
                 else
                   stop_state<=stop_begin;
     stop_bit: if(scl)
                  begin
                   stop_buf<=stop_buf<<1;
                   stop_state<=stop_end;
                  end
                else
                  stop_state<=stop_bit;
      stop_end: if(!scl)
                  begin
                    link_sda<=1'b0;
                    link_stop<=1'b0;
                    //link_write<=1'b0;
                    ack_f<=1'b1;
                  end
                else
                  stop_state<=stop_end;
        endcase
    end
 endtask
              
 
  always@(negedge clk)    //產(chǎn)生scl
    begin
      if(reset)
         scl<=0;
      else
         scl<=~scl;
     end

always@(posedge clk)
if(reset)
  begin
    link_read<=1'b0;
    link_write<=1'b0;
    link_head<=1'b0;
    link_stop<=1'b0;
    link_sda<=1'b0;
    ack=1'b0;
    ack_f=1'b0;
    head_buf<=2'b00;
    stop_buf<=2'b00;
    wf<=1'b0;
    rf<=1'b0;
    main_state<=idle;
  end
else
  begin
  casex(main_state)
     idle: begin
          link_read<=1'b0;
          link_write<=1'b0;
          link_head<=1'b0;
          link_stop<=1'b0;
          link_sda<=1'b0;
          if(wr)
            begin
             wf<=1'b1; 
             main_state<=ready;
            end
          else if(rd)
            begin
            rf<=1'b1;
            main_state<=ready;
            end
          else
            begin
            rf<=1'b0;
            wf<=1'b0;
            main_state<=idle;
            end
          end
   ready: begin
           link_head<=1'b1;
           link_sda<=1'b1; 
           head_buf<=2'b10;
           stop_buf<=2'b01;
           head_state<=head_begin;
           main_state<=write_start;
           end
 write_start: if(ack_f==1'b0)
           head;
           else
             begin
               storage_buf<={1'b1,1'b0,1'b1,1'b0,addr[10:8],1'b0};
               link_head<=1'b0;
               link_write<=1'b1;
               ack_f<=1'b0;
               w_state<=data_to_sda_6;
               main_state<=ctrl_write;
              end  
ctrl_write: if(ack_f==1'b0)
             perallel_to_serial;
           else
             begin
               w_state<=data_to_sda_7;
               ack_f<=1'b0;
               storage_buf<=addr[7:0];
               main_state<=addr_write;
             end
 addr_write: if(ack_f==1'b0)
               perallel_to_serial;
             else if(wf==1'b1)
               begin
                 ack_f<=1'b0;
                 main_state<=data_write;
                 storage_buf<=data;
                 w_state<=data_to_sda_7;
               end
             else if(rf==1'b1)
               begin
                 ack_f<=1'b0;
                 main_state<=read_start;
                 head_state<=head_begin;
                 head_buf<=2'b10;
               end
data_write: if(ack_f==1'b0)
             perallel_to_serial;
           else
             begin
             ack_f<=1'b0;
             main_state<=stop;
             stop_state<=stop_begin;
            // link_write<=1'b0;
           end
read_start:if(ack_f==1'b0)
             head;
           else
             begin
             ack_f<=1'b0;
             main_state<=ctrl_read;
             link_head<=1'b0;
             storage_buf<={1'b1,1'b0,1'b1,1'b0,addr[10:8],1'b1};
             link_write<=1'b1;
             link_sda<=1'b1;
             w_state<=data_to_sda_6;
             end
ctrl_read: if(ack_f==1'b0)
             perallel_to_serial;
           else
            begin
             ack_f<=1'b0;
             link_write<=1'b0;
             link_sda<=1'b0;
             r_state<=sda_to_data_begin;
             main_state<=data_read;
           end
 data_read: if(ack_f==1'b0)
               serial_to_perallel;
             else 
               begin
               ack_f<=1'b0;
               main_state<=stop;
               stop_state<=stop_bit;
               link_stop<=1'b1;
               link_sda<=1'b1;
               end
   stop: if(ack_f==1'b0)
            stop_1;
          else 
          begin
          ack<=1'b1;
          ack_f<=1'b0;
          main_state<=ackn;
          end
   ackn: begin
          ack<=1'b0;
          wf<=1'b0;
          rf<=1'b0;
          main_state<=idle;
         end
 default:main_state<=idle;
 endcase
 end
                                                                  
     
endmodule

這里我想特別強調(diào)一下雙向端口sda沛厨,究竟何時是輸入端口何時是輸出端口呢宙地?在進(jìn)行寫入數(shù)據(jù)和控制字的寫入時是輸出端口,在進(jìn)行應(yīng)答位和數(shù)據(jù)讀出時是接受外部數(shù)據(jù)的輸入端口逆皮。

  • link_sda是控制sda寫入的開關(guān)
  • out_flag來自EEPROM的內(nèi)部信號用于控制sda的輸入宅粥。
    寫過程雙向sda信號的驅(qū)動.png
    讀過程雙向sda信號的驅(qū)動.png

    通過讀寫過程的波形圖,我們可以看出电谣,在讀寫過程中秽梅,link_sda和out_flag總是有一個信號保持高電平,這樣的話才能保持sda信號有波形剿牺。
signal

為了測試EEPROM_WR企垦,signal模塊能夠?qū)Ρ粶y試模塊產(chǎn)生的ack信號產(chǎn)生相應(yīng),發(fā)出模仿MCU的數(shù)據(jù)晒来、地址信號和讀寫信號钞诡;被測試的模塊在接收到信號后會發(fā)出讀寫EEPROM虛擬模塊的信號。
本模塊為行為模塊,不能綜合成門級網(wǎng)表荧降。

`timescale 1ns/1ns
`define timeslice 200
module signal(data,
          reset,
          clk,
          rd,
          wr,
          addr,
          ack
        );
 input ack;
 output clk,reset,rd,wr;
 output[10:0] addr;
 output[7:0] data;

 wire[7:0] data;
 reg clk,reset,rd,wr;
 reg[10:0] addr;
 reg W_R;
 reg[7:0] data_to_eeprom;
 reg[10:0] addr_mem[0:255];
 reg[7:0] data_mem[0:255];
 reg[7:0] ROM[0:2047];
 integer i,j;
 integer OUTFILE;

 parameter test_number=50;

  assign data=W_R ? 8'hzz : data_to_eeprom;

  always # (`timeslice/2)
  clk=~clk;

 initial
   begin
   reset=1;
   i=0;
   j=0;
    W_R=0;
    clk=0;
    rd=0;
    wr=0;
   # 1000
     reset=0;
 repeat(test_number)
 begin
   #(5 * `timeslice)
   wr=1;
   #(`timeslice)
   wr=0;
   @(posedge ack);
  end
  #(10 * `timeslice)
  W_R=1;
repeat(test_number)
  begin
    #(5 * `timeslice)
    rd=1;
    #(`timeslice)
    rd=0;
    @(posedge ack);
   end
 end

 initial
  begin
   OUTFILE=$fopen("C:/Users/XQ/Desktop/eeprom_dat.txt");
   $readmemh("C:/Users/XQ/Desktop/addr_dat.txt",addr_mem);
   $readmemh("C:/Users/XQ/Desktop/data_dat.txt",data_mem);
 end
 
initial 
begin
  $display("writing-------------------------------writing");
  #(2*`timeslice)
  for(i=0;i<=test_number;i=i+1)
    begin
      addr=addr_mem[i];
      data_to_eeprom=data_mem[i];
      $fdisplay(OUTFILE,"@%0h   %0h",addr,data_to_eeprom);
      @(posedge ack);
     end
   end  

  initial
  @(posedge W_R)
 begin
addr=addr_mem[0];
$fclose(OUTFILE);
$readmemh("C:/Users/XQ/Desktop/eeprom_dat.txt",ROM);
$display("begin----------------------reading");
 for(j=0;j<=test_number;j=j+1)
   begin
     addr=addr_mem[j];
     @(posedge ack)
     if(data==ROM[addr])
       $display("data %0h == ROM[%0h]",data,addr);
     else
       $display("data %0h != ROM[%0h]",data,addr);
     end
   end
EEPROM_ALL_TOP

將各個部分集成在一起

`timescale 1ns/1ns
`define timeslice 200
module EEPROM_ALL_top;

   wire[7:0] data;
   wire[10:0] addr;
   wire reset;
   wire clk,rd,wr,ack;
   wire sda,scl;

   parameter test_numbers=5;  

     initial
     begin        
    #(`timeslice*180*test_numbers)
    $stop;
   end

    signal #(test_numbers) signal_1(.data(data),
                             .reset(reset),
                               .clk(clk),
                                .rd(rd),
                                .wr(wr),
                              .addr(addr),
                              .ack(ack));
                              
  EEPROM EEPROM_1 (.scl(scl),.sda(sda));

    EEPROM_WR EEPROM_WR_1 (.sda(sda),
                     .scl(scl),
                     .ack(ack),
                     .reset(reset),
                     .clk(clk),
                     .wr(wr),
                     .rd(rd),
                     .addr(addr),
                     .data(data));

endmodule

總結(jié):其實要想徹底搞清楚這個復(fù)雜時序邏輯的工作機(jī)制接箫,還是需要大家真正上手寫一遍代碼

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市朵诫,隨后出現(xiàn)的幾起案子辛友,更是在濱河造成了極大的恐慌,老刑警劉巖剪返,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件废累,死亡現(xiàn)場離奇詭異,居然都是意外死亡随夸,警方通過查閱死者的電腦和手機(jī)九默,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宾毒,“玉大人驼修,你說我怎么就攤上這事≌╊酰” “怎么了乙各?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長幢竹。 經(jīng)常有香客問我耳峦,道長,這世上最難降的妖魔是什么焕毫? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任蹲坷,我火速辦了婚禮,結(jié)果婚禮上邑飒,老公的妹妹穿的比我還像新娘循签。我一直安慰自己,他們只是感情好疙咸,可當(dāng)我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布县匠。 她就那樣靜靜地躺著,像睡著了一般撒轮。 火紅的嫁衣襯著肌膚如雪乞旦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天题山,我揣著相機(jī)與錄音兰粉,去河邊找鬼。 笑死顶瞳,一個胖子當(dāng)著我的面吹牛亲桦,可吹牛的內(nèi)容都是我干的崖蜜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼客峭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了抡柿?” 一聲冷哼從身側(cè)響起舔琅,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎洲劣,沒想到半個月后备蚓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡囱稽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年郊尝,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片战惊。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡流昏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吞获,到底是詐尸還是另有隱情况凉,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布各拷,位于F島的核電站刁绒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏烤黍。R本人自食惡果不足惜知市,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望速蕊。 院中可真熱鬧嫂丙,春花似錦、人聲如沸互例。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽媳叨。三九已至腥光,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間糊秆,已是汗流浹背武福。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留痘番,地道東北人捉片。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓平痰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親伍纫。 傳聞我的和親對象是個殘疾皇子宗雇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容