FPGA project : IIC_wr_eeprom

简介:

简单双向二线制,同步串行总线。

scl:串行时钟线,用于同步通讯数据。

sda:双向串行数据线。

物理层:

1,支持挂载多设备。

2,二线制。

3,每个设备有其单独的地址。

4,空闲时,sda会被上拉电阻拉高。

5,存在多个主机时,通过仲裁逻辑决定那个主机控制总线。

6,三个速度模式:标准模式(100kb/s);快速模式(400kb/s);高速模式(3.4Mb/s)

地址:

器件地址。7bit,最后1bit为读写控制位。

存储地址:分为单字节和双字节,与存储设备容量有关。就是有多少byte的容量,用几位二进制地址表示。

读写地址。

时序总结:

在scl为高时,若sda变化,则为起始或终止信号。

在scl为低时,(已启动读时隙),sda在scl低电平变化,高电平对sda采样。

读时序:分为随机读(单字节读)和顺序读(页读)。

写时序:单字节写和页写。

框图:

时序图也画了,很多很大,就不放了。

 代码:

iic时序驱动模块+指令控制模块+按键消抖+顶层;

/************************************************************
****************    iic 模块说明    ************************
****************    驱动接口模块    ************************
*输入端口:
*sys_clk    :   1Mhz时钟信号。
*iic_start  :   开始进行读写通信标志信号。
*en_w       :   写使能信号,与iic_start同时拉高,iic模块启动写时序。
*addr       :   地址信号,读写公用一个地址信号。
*data_w     :   要通过iic协议写入从机的8bit数据。
*en_r       :   读使能信号,与iic_start同时拉高,iic模块启动读时序。
*addr_num   :   由于地址有单byte和双byte情况,addr_num == 0表示单。
*输出端口:
*scl        :   iic协议的同步时钟信号。串行时钟线,用于同步通讯数据。时钟频率为250kHz
*sda        :   双向端口,双向串行数据线。
*data_out   :   读取到的1byte数据。
*iic_end    :   完成ibyte数据的读写标志信号。
*/
module iic (input       wire            sys_clk     , // 虽然写的是sys_clk但是例化时要接iic_clkinput       wire            sys_rst_n   ,input       wire            iic_start   ,input       wire            en_w        ,input       wire            en_r        ,input       wire    [15:0]  byte_addr   ,input       wire    [7:0]   data_w      ,input       wire            addr_num    ,inout       wire            sda         ,output      reg             scl         ,output      reg     [7:0]   data_out    ,output      reg             iic_end     
);// parameterparameter   DEVICE_ADDR = 7'b1010_011 ; // 器件地址,最后一位要根据读写,来决定。[6:0]wire        [7:0]   FIRST_ADDR        ; // AT24C64wire        [7:0]   SECOND_ADDR       ; // 可在此设置读写地址。assign      FIRST_ADDR  = byte_addr[15:8] ;assign      SECOND_ADDR = byte_addr[ 7:0] ;// localparam localparam  IDLE                    =4'b0000 ,START1                  =4'b0001 ,SEND_DEVICE_ADDR        =4'b0011 ,ACK1                    =4'b0010 ,SEND_FIRST_ADDR         =4'b0110 ,ACK2                    =4'b0111 ,SEND_SECOND_ADDR        =4'b0101 ,ACK3                    =4'b0100 ,WR_DATA                 =4'b1100 ,ACK4                    =4'b1101 ,STOP                    =4'b1111 ,START2                  =4'b1110 ,SEND_READ_DEVICE_ADDR   =4'b1010 ,ACK5                    =4'b1011 ,READ_DATA               =4'b1001 ,NO_ACK                  =4'b1000 ; // wire signal definewire    sda_en ;wire    IDLEtoSTART1                ;             wire    START1toSEND_DEVICE_ADDR    ; wire    SEND_DEVICE_ADDRtoACK1      ;   wire    ACK1toSEND_FIRST_ADDR       ;wire    ACK1toSEND_SECOND_ADDR      ;   wire    SEND_FIRST_ADDRtoACK2       ;    wire    ACK2toSEND_SECOND_ADDR      ;   wire    SEND_SECOND_ADDRtoACK3      ;   wire    ACK3toWR_DATA               ;            wire    ACK3toSTART2                ;             wire    WR_DATAtoACK4               ;            wire    ACK4toSTOP                  ;               wire    STOPtoIDLE                  ;     wire    START2toSEND_READ_DEVICE_ADDR;wire    SEND_READ_DEVICE_ADDRtoACK5 ; wire    ACK5toREAD_DATA             ;          wire    READ_DATAtoNO_ACK           ;        wire    NO_ACKtoSTOP                ;             // reg signal definereg     [3:0]   state_c ;reg     [3:0]   state_n ;reg     [1:0]   cnt_iic ; // 关键计数器。很多信号赋值都与他有关。reg     [2:0]   cnt_bit ; // bit计数器,计数值0-7reg             sda_out ;
/***********************************************************************/// 状态机描述// reg     [3:0]   state_c ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) state_c <= IDLE ;elsestate_c <= state_n ;end// reg     [3:0]   state_n ;always @(*) begincase(state_c)IDLE                 :  if(IDLEtoSTART1) state_n = START1 ;else state_n = IDLE ;START1               :  if(START1toSEND_DEVICE_ADDR)state_n = SEND_DEVICE_ADDR ;else state_n = START1 ;SEND_DEVICE_ADDR     :  if(SEND_DEVICE_ADDRtoACK1) state_n = ACK1 ;else state_n = SEND_DEVICE_ADDR ;ACK1                 :  if(ACK1toSEND_FIRST_ADDR) state_n = SEND_FIRST_ADDR ;else if(ACK1toSEND_SECOND_ADDR)state_n = SEND_SECOND_ADDR ;else state_n = ACK1 ;SEND_FIRST_ADDR      :  if(SEND_FIRST_ADDRtoACK2) state_n = ACK2 ;else state_n = SEND_FIRST_ADDR ;ACK2                 :  if(ACK2toSEND_SECOND_ADDR) state_n = SEND_SECOND_ADDR ;else state_n = ACK2 ;SEND_SECOND_ADDR     :  if(SEND_SECOND_ADDRtoACK3) state_n = ACK3 ;else state_n = SEND_SECOND_ADDR ;ACK3                 :  if(ACK3toWR_DATA) state_n = WR_DATA ;else if(ACK3toSTART2)state_n = START2 ;else state_n = ACK3 ;WR_DATA              :  if(WR_DATAtoACK4) state_n = ACK4 ;else state_n = WR_DATA ;ACK4                 :  if(ACK4toSTOP) state_n = STOP ;else state_n = ACK4 ;STOP                 :  if(STOPtoIDLE) state_n = IDLE ;else state_n = STOP ;START2               :  if(START2toSEND_READ_DEVICE_ADDR) state_n = SEND_READ_DEVICE_ADDR ;else state_n = START2 ;SEND_READ_DEVICE_ADDR:  if(SEND_READ_DEVICE_ADDRtoACK5) state_n = ACK5 ;else state_n = SEND_READ_DEVICE_ADDR ;ACK5                 :  if(ACK5toREAD_DATA) state_n = READ_DATA ;else state_n = ACK5 ;READ_DATA            :  if(READ_DATAtoNO_ACK) state_n = NO_ACK ;else state_n = READ_DATA ;NO_ACK               :  if(NO_ACKtoSTOP) state_n = STOP ;else state_n = NO_ACK ;default              :      state_n = IDLE ;endcaseend// 状态转移条件赋值:assign  IDLEtoSTART1             = (state_c == IDLE  ) && (iic_start == 1'b1) ;assign  START1toSEND_DEVICE_ADDR = (state_c == START1) && (cnt_iic == 3)      ;assign  SEND_DEVICE_ADDRtoACK1   = (state_c == SEND_DEVICE_ADDR) && (cnt_iic == 3 && cnt_bit == 7) ;assign  ACK1toSEND_FIRST_ADDR    = (state_c == ACK1  ) && (cnt_iic == 3 && sda == 1'b0 && addr_num == 1) ; //&& sda == 1'b0 由于仿真模型没有相应ack功能,所以要自己模拟。assign  ACK1toSEND_SECOND_ADDR   = (state_c == ACK2  ) && (cnt_iic == 3 && sda == 1'b0 && addr_num == 0) ; //&& sda == 1'b0assign  SEND_FIRST_ADDRtoACK2    = (state_c == SEND_FIRST_ADDR) && (cnt_iic == 3 && cnt_bit == 7) ;assign  ACK2toSEND_SECOND_ADDR   = (state_c == ACK2  ) && (cnt_iic == 3 && sda == 0) ; //&& sda == 0assign  SEND_SECOND_ADDRtoACK3   = (state_c == SEND_SECOND_ADDR) && (cnt_iic == 3 && cnt_bit == 7) ;assign  ACK3toWR_DATA            = (state_c == ACK3  ) && (cnt_iic == 3 && en_w && sda == 0) ; // && sda == 0 assign  ACK3toSTART2             = (state_c == ACK3  ) && (cnt_iic == 3 && en_r && sda == 0) ; // && sda == 0 assign  WR_DATAtoACK4            = (state_c == WR_DATA ) && (cnt_iic == 3 && cnt_bit == 7) ;assign  ACK4toSTOP               = (state_c == ACK4  ) && (cnt_iic == 3 && sda == 0) ; // && sda == 0assign  STOPtoIDLE               = (state_c == STOP  ) && (cnt_iic == 3 && cnt_bit == 3) ;assign  START2toSEND_READ_DEVICE_ADDR = (state_c == START2) && (cnt_iic == 3)      ;assign  SEND_READ_DEVICE_ADDRtoACK5 = (state_c == SEND_READ_DEVICE_ADDR) && (cnt_iic == 3 && cnt_bit == 7) ;assign  ACK5toREAD_DATA          = (state_c == ACK5  ) && (cnt_iic == 3 && sda == 0) ; //&& sda == 0assign  READ_DATAtoNO_ACK        = (state_c == READ_DATA) && (cnt_iic == 3 && cnt_bit == 7) ;assign  NO_ACKtoSTOP             = (state_c ==  NO_ACK) && (cnt_iic == 3 && sda == 1) ;// reg     [1:0]   cnt_iic ; // 关键计数器。很多信号赋值都与他有关。always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_iic <= 2'd0 ;else if(state_c != IDLE)cnt_iic <= cnt_iic + 1'b1 ;else cnt_iic <= 1'b0 ;end// reg     [2:0]   cnt_bit ; // bit计数器,计数值0-7always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_bit <= 3'd0 ;else if(state_c != IDLE && state_c != START1 && state_c != START2 && state_c != NO_ACK && state_c != ACK1 && state_c != ACK2 && state_c != ACK3 && state_c != ACK4 && state_c != ACK5 && cnt_iic == 3)cnt_bit <= cnt_bit + 1'b1 ;else if(state_c != IDLE && state_c != START1 && state_c != START2 && state_c != NO_ACK && state_c != ACK1 && state_c != ACK2 && state_c != ACK3 && state_c != ACK4 && state_c != ACK5)cnt_bit <= cnt_bit ;else cnt_bit <= 3'd0 ;end// reg             sda_out ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n)sda_out <= 1'b1 ; elsecase (state_c)IDLE                 :  sda_out <= 1'b1 ;START1               :  if(cnt_iic == 0) sda_out <= 1'b0 ;else sda_out <= sda_out ;SEND_DEVICE_ADDR     :  if(cnt_iic == 0 && cnt_bit != 7) sda_out <= DEVICE_ADDR[6 - cnt_bit] ;else if(cnt_iic == 0 && cnt_bit == 7) sda_out <= 1'b0 ; // 写控制位。ACK1                 :  sda_out <= 1'b0 ;SEND_FIRST_ADDR      :  if(cnt_iic == 0)sda_out <= FIRST_ADDR[7 - cnt_bit] ;else sda_out <= sda_out ;ACK2                 :  sda_out <= 1'b0 ;SEND_SECOND_ADDR     :  if(cnt_iic == 0)sda_out <= SECOND_ADDR[7 - cnt_bit] ;else sda_out <= sda_out ;ACK3                 :  sda_out <= 1'b0 ;WR_DATA              :  if(cnt_iic == 0)sda_out <= data_w[7 - cnt_bit] ;else sda_out <= sda_out ;ACK4                 :  sda_out <= 1'b0 ;STOP                 :  if(cnt_iic == 0 && cnt_bit == 0)sda_out <= 1'b0 ;else if(cnt_iic == 2 && cnt_bit == 0)sda_out <= 1'b1 ;else    sda_out <= sda_out ;START2               :  if(cnt_iic == 0)sda_out <= 1'b1 ;else if(cnt_iic == 2)sda_out <= 1'b0 ;else sda_out <= sda_out ;SEND_READ_DEVICE_ADDR:  if(cnt_iic == 0 && cnt_bit != 7) sda_out <= DEVICE_ADDR[6 - cnt_bit] ;else if(cnt_iic == 0 && cnt_bit == 7) sda_out <= 1'b1 ; // 读控制位。ACK5                 :  sda_out <= 1'b0 ;READ_DATA            :  sda_out <= 1'b0 ;NO_ACK               :  sda_out <= 1'b1 ;default              :  sda_out <= 1'b1 ;endcaseend// wire     sda_en assign sda_en = ((state_c == ACK1) || (state_c == ACK2) || (state_c == ACK3) || (state_c == ACK4) || (state_c == ACK5) || (state_c == READ_DATA)) ? 1'b0 : 1'b1 ;
/***************************************************************************/// wire            sda         ,assign sda = (sda_en == 1) ? sda_out : 1'bz ;// reg             scl         ,always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) scl <= 1'b1 ;else if(state_c != IDLE && state_c != STOP && state_c != START1) beginif(cnt_iic == 1 || cnt_iic == 3)scl <= ~scl ;else scl <=  scl ;end else if(state_c == IDLE)scl <= 1'b1 ;else if(state_c == STOP && (cnt_bit == 0 && cnt_iic == 1))scl <= 1'b1 ;else if(state_c == STOP)scl <= scl ;else if(state_c == START1 && cnt_iic == 3)scl <= ~scl ;else if(state_c == START1)scl <= scl ;else scl <= 1'b1 ;end// reg     sda_data ;// always @(posedge sys_clk or negedge sys_rst_n) begin//     if(~sys_rst_n)//         sda_data <= 1'b0 ;//     else if(state_c == READ_DATA && cnt_iic == 0)//         sda_data <= ~sda_data ;//     else    //         sda_data <=  sda_data ;// end// reg [7:0]    data_outalways @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) data_out <= 8'd0 ;else if(state_c == READ_DATA && cnt_iic == 2 && scl == 1)data_out <= {data_out[6:0],sda} ; // 这里也需要自己模拟 sda_dataelse data_out <= data_out ;end// wire            iic_end     always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) iic_end <= 1'b0 ;else if(state_c == STOP && cnt_iic == 3 && cnt_bit == 3)iic_end <= 1'b1 ;else    iic_end <= 1'b0 ;end
endmodule
/************************************************************
****************    iic_instruct 模块说明    ************************
****************    产生接口时序模块的控制信号,并存储读到的数据,并把数据传给数码管显示模块。
*/
module iic_instruct (input       wire            sys_clk   , // 20nsinput       wire            sys_rst_n ,input       wire            iic_clk   , // 1000nsinput       wire            flag_w    ,input       wire            flag_r    ,input       wire            iic_end   ,input       wire    [7:0]   data_r    , // iic 模块读到的1byte数据。output      reg             iic_start ,output      reg             en_w      , // 写使能,往eeprom中写数据的使能信号。output      reg             en_r      , // 读使能,从eeprom中读数据的使能信号。output      reg     [15:0]  byte_addr , // 读写操作的数据地址。output      reg     [7:0]   data_w    , // 往eeprom中写入的数据。output      wire            addr_num  , // eeprom的存储地址是几个byte。output      wire    [7:0]   data_out    // 传给数码管显示的数据。
);parameter   ADDR_START          = 16'h00_00 ,DATA_WRITE          = 8'd00     , // 写入的起始数据。CNT_MAX_START       = 49999     , // 5msCNT_MAX_1S          = 1_000_000 ,CNT_MAX_WRITE_BYTE  = 10        , CNT_MAX_READ_BYTE   = 10        ; 
/******************************************************/// 第一步:处理输入信号,实现快速时钟域标志信号同步到慢速时钟域。  // 也就是保证慢速时钟域可以检测到标志信号。reg             valid_write ;reg     [7:0]   cnt_write   ;reg             valid_read  ;reg     [7:0]   cnt_read    ;reg     [15:0]  cnt_read_byte   ;reg     [15:0]  cnt_start       ;reg     [15:0]  cnt_write_byte  ; // 写入eeprom字节计数器wire	        empty   ;wire	        full    ;wire	[9:0]   usedw   ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) valid_write <= 1'b0 ;else if(flag_w)valid_write <= 1'b1 ;else if(cnt_write == 199)valid_write <= 1'b0 ;else valid_write <=  valid_write ;endalways @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_write <= 8'd0 ;else if(valid_write && cnt_write == 199)cnt_write <= 8'd0 ;else if(valid_write)cnt_write <= cnt_write + 1'b1 ;else cnt_write <= 8'd0 ;endalways @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) valid_read <= 1'b0 ;else if(flag_r)valid_read <= 1'b1 ;else if(cnt_read == 199)valid_read <= 1'b0 ;else valid_read <=  valid_read ;endalways @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_read <= 8'd0 ;else if(valid_read && cnt_read == 199)cnt_read <= 8'd0 ;else if(valid_read)cnt_read <= cnt_read + 1'b1 ;else cnt_read <= 8'd0 ;endassign addr_num = 1'b1 ;
/**********************************************************************************/// 第二步:产生写数据相关信号的产生。在iic_clk时钟域下。// en_walways @(posedge iic_clk or negedge sys_rst_n) beginif(~sys_rst_n) en_w <= 1'b0 ;else if(iic_end && (cnt_write_byte == CNT_MAX_WRITE_BYTE - 1))en_w <= 1'b0 ;else if(valid_write)en_w <= 1'b1 ;else en_w <= en_w ;end//reg    iic_startalways @(posedge iic_clk or negedge sys_rst_n) beginif(~sys_rst_n)iic_start <= 1'b0 ;else if(en_w == 0 && valid_write == 1 || cnt_start == CNT_MAX_START - 1)iic_start <= 1'b1 ;else iic_start <= 1'b0 ;end// reg   [15:0]  cnt_start ;always @(posedge iic_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_start <= 16'd0 ;else if(((en_w == 1) && ((cnt_start == CNT_MAX_START - 1)|| (iic_end == 1 && cnt_write_byte == CNT_MAX_WRITE_BYTE - 1))) || ((en_r == 1) && ((cnt_start == CNT_MAX_START - 1)|| (iic_end == 1 && cnt_read_byte == CNT_MAX_READ_BYTE - 1))))cnt_start <= 16'd0 ;else if(en_w == 1 || en_r)cnt_start <= cnt_start + 1'b1 ;else cnt_start <= 16'd0 ;end// [15:0] byte_addr // 目前只完成了写地址,always @(posedge iic_clk or negedge sys_rst_n) beginif(~sys_rst_n) byte_addr <= ADDR_START ;else if((iic_end == 1 && cnt_write_byte == CNT_MAX_WRITE_BYTE - 1) || (iic_end == 1 && cnt_read_byte == CNT_MAX_READ_BYTE - 1))byte_addr <= ADDR_START ;else if(iic_end == 1)byte_addr <= byte_addr + 1'b1 ;else byte_addr <= byte_addr ;end// [7:0]    data_walways @(posedge iic_clk or negedge sys_rst_n) beginif(~sys_rst_n) data_w <= DATA_WRITE ;else if(iic_end == 1 && cnt_write_byte == CNT_MAX_WRITE_BYTE - 1)data_w <= DATA_WRITE ;else if(en_w && iic_end == 1)data_w <= data_w + 1'b1 ;else data_w <= data_w ;end// [15:0]   cnt_write_bytealways @(posedge iic_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_write_byte <= 16'd0 ;else if(en_w && iic_end == 1 && cnt_write_byte == CNT_MAX_WRITE_BYTE - 1)cnt_write_byte <= 16'd0 ;else  if(en_w && iic_end == 1)cnt_write_byte <= cnt_write_byte + 1'b1 ;else cnt_write_byte <= cnt_write_byte ;end
/*****************************************************************************/// 读相关控制信号产生// en_ralways @(posedge iic_clk or negedge sys_rst_n) beginif(~sys_rst_n)en_r <= 1'b0 ;else if(iic_end == 1 && cnt_read_byte == CNT_MAX_READ_BYTE - 1)en_r <= 1'b0 ;else if(valid_read)en_r <= 1'b1 ;else en_r <= en_r ;end// [15:0]  cnt_read_byte always @(posedge iic_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_read_byte <= 16'd0 ;else if(en_r && iic_end == 1 && cnt_read_byte == CNT_MAX_READ_BYTE - 1)cnt_read_byte <= 16'd0 ;else  if(en_r && iic_end == 1)cnt_read_byte <= cnt_read_byte + 1'b1 ;else cnt_read_byte <= cnt_read_byte ;end
/*******************************************************************************/reg             valid_fifo_read ;reg     [19:0]  cnt_1s          ;reg             fifo_rd_en      ;// valid_fifo_readalways @(posedge iic_clk or negedge sys_rst_n) beginif(~sys_rst_n)valid_fifo_read <= 1'b0 ;else if(valid_fifo_read == 1 && usedw == 0)valid_fifo_read <= 1'b0 ;else if(usedw > (CNT_MAX_READ_BYTE - 1))valid_fifo_read <= 1'b1 ;else valid_fifo_read <= valid_fifo_read ;end// [19:0]  cnt_1s    always @(posedge iic_clk or negedge sys_rst_n) beginif(~sys_rst_n)cnt_1s <= 20'd0 ;else if(valid_fifo_read == 1 && cnt_1s == CNT_MAX_1S - 1)cnt_1s <= 20'd0 ;else if(valid_fifo_read == 1)cnt_1s <= cnt_1s + 1'b1 ;else cnt_1s <= 20'd0 ;end// fifo_rd_enalways @(posedge iic_clk or negedge sys_rst_n) beginif(~sys_rst_n)fifo_rd_en <= 1'b0 ;else if(valid_fifo_read == 1 && cnt_1s == CNT_MAX_1S - 1)fifo_rd_en <= 1'b1 ;else fifo_rd_en <= 1'b0 ;endfifo_8x1024 fifo_8x1024_inst(.clock       ( iic_clk          ) ,.data        ( data_r           ) ,.rdreq       ( fifo_rd_en       ) ,.wrreq       ( en_r && iic_end  ) ,.empty       ( empty            ) ,.full        ( full             ) ,.q           ( data_out         ) ,.usedw       ( usedw            )  
);
endmodule

 

module top (input       wire        sys_clk     ,input       wire        sys_rst_n   ,input       wire        key_write   ,input       wire        key_read    ,inout       wire        sda         ,output      wire        scl         ,output      wire        ds          ,output      wire        oe          ,output      wire        shcp        ,output      wire        stcp        
);// 例化间连线wire            clk_50mHz   ;wire            clk_1mHz    ; wire            locked      ;  wire            rst_n       ;wire            flag_write  ;wire            flag_read   ;wire    [05:00] point       ;wire            sign        ;assign          point  = 5'd0 ;assign          sign   = 1'b0 ;assign          rst_n = sys_rst_n && locked ;pll pll_isnt(.areset                 ( ~sys_rst_n ) ,.inclk0                 ( sys_clk    ) ,.c0                     ( clk_50mHz  ) ,.c1                     ( clk_1mHz   ) ,.locked                 ( locked     ) 
);key_filter key_filter_inst_w(.sys_clk                ( clk_50mHz ) ,.sys_rst_n              ( rst_n     ) ,.key_in                 ( key_write ) ,.key_out                ( flag_write)         
);   
key_filter key_filter_inst_r(.sys_clk                ( clk_50mHz ) ,.sys_rst_n              ( rst_n     ) ,.key_in                 ( key_read  ) ,.key_out                ( flag_read )         
); wire            iic_start ;wire            en_w      ;wire            en_r      ;wire    [15:0]  byte_addr ;wire    [7:0]   data_w    ;wire            addr_num  ;wire    [7:0]   data_out  ;wire            iic_end   ;wire    [7:0]   data_r    ;
iic_instruct iic_instruct_inst(.sys_clk                ( clk_50mHz  ) , // 20ns.sys_rst_n              ( rst_n      ) ,.iic_clk                ( clk_1mHz   ) , // 1000ns.flag_w                 ( flag_write ) ,.flag_r                 ( flag_read  ) ,.iic_end                ( iic_end    ) ,.data_r                 ( data_r     ) , // iic 模块读到的1byte数据。.iic_start              ( iic_start  ) ,.en_w                   ( en_w       ) , // 写使能,往eeprom中写数据的使能信号。.en_r                   ( en_r       ) , // 读使能,从eeprom中读数据的使能信号。.byte_addr              ( byte_addr  ) , // 读写操作的数据地址。.data_w                 ( data_w     ) , // 往eeprom中写入的数据。.addr_num               ( addr_num   ) , // eeprom的存储地址是几个byte。.data_out               ( data_out   )   // 传给数码管显示的数据。
);iic iic_inst(.sys_clk                ( clk_1mHz   ) , // 虽然写的是sys_clk但是例化时要接iic_clk.sys_rst_n              ( rst_n      ) ,.iic_start              ( iic_start  ) ,.en_w                   ( en_w       ) ,.en_r                   ( en_r       ) ,.byte_addr              ( byte_addr  ) ,.data_w                 ( data_w     ) ,.addr_num               ( addr_num   ) ,.sda                    ( sda        ) ,.scl                    ( scl        ) ,.data_out               ( data_r     ) ,.iic_end                ( iic_end    )     
);seg_595_dynamic seg_595_dynamic_isnt(.sys_clk                ( clk_50mHz ) ,.sys_rst_n              ( rst_n     ) ,.data                   ( {12'd0,data_out} ) , .point                  ( point     ) ,.sign                   ( sign      ) ,.seg_en                 ( rst_n     ) ,.ds                     ( ds        ) ,      .oe                     ( oe        ) ,      .shcp                   ( shcp      ) ,      .stcp                   ( stcp      )           
);endmodule

仿真测试,要用到 M24C64仿真模型。

仿真验证通过,上板验证通过。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/166695.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装visual studio报错“无法安装msodbcsql“

在安装visual studio2022时安装完成后提示无法安装msodbcsql, 查看日志文件详细信息提示&#xff1a;指定账户已存在。 未能安装包“msodbcsql,version17.2.30929.1,chipx64,languagezh-CN”。 搜索 URL https://aka.ms/VSSetupErrorReports?qPackageIdmsodbcsql;PackageActi…

分布式缓存Spring Cache

一、缓存里的数据如何和数据库的数据保持一致&#xff1f; 缓存数据一致性1)、双写模式2)、失效模式1、缓存数据一致性-双写模式 2、 缓存数据一致性-失效模式 我们系统的一致性解决方案: 1、缓存的所有数据都有过期时间&#xff0c;数据过期下一次查询触发主动更新 2、读写数据…

Android 10 中的隐私权变更

Android 10 中的隐私权变更 重大变更外部存储访问权限范围限定为应用文件和媒体在后台运行时访问设备位置信息需要权限以 Android 9 或更低版本为目标平台时自动授予访问权限在设备升级到 Android 10 后访问针对从后台启动 Activity 的限制标识符和数据移除了联系人亲密程度信息…

JIT耗时优化

优质博文&#xff1a;IT-BLOG-CN 一、背景 业务流量突增&#xff0c;机器直接接入大量流量QPS2000&#xff0c;JIT和GC会消耗太多CPU资源&#xff0c;导致1-2分钟时间内的请求超时导致异常&#xff0c;因此采用流量预热的方式&#xff0c;让机器逐步接入流量&#xff0c;需要预…

go语言Array 与 Slice

有的语言会把数组用作常用的基本的数据结构&#xff0c;比如 JavaScript&#xff0c;而 Golang 中的数组(Array)&#xff0c;更倾向定位于一种底层的数据结构&#xff0c;记录的是一段连续的内存空间数据。但是在 Go 语言中平时直接用数组的时候不多&#xff0c;大多数场景下我…

【Lua语法】字符串

Lua语言中的字符串是不可变值。不能像在C语言中那样直接改变某个字符串中的某个字符&#xff0c;但是可以通过创建一个新字符串的方式来达到修改的目的 print(add2(1 , 2 ,15,3))a "no one"b string.gsub(a , "no" , "on1111")print(a) print…

微软正式发布开源应用平台 Radius平台

“ 10 月 18 日&#xff0c;微软 Azure 孵化团队正式发布开源应用平台 Radius&#xff0c;该平台将应用程序置于每个开发阶段的中心&#xff0c;重新定义应用程序的构建、管理与理解方式。” 简单的概括就是&#xff0c;它和Kubernetes不一样&#xff0c;Radius将应用程序放在每…

C语言--程序环境和预处理

前言 本章就是c语言的最后一个板块了&#xff0c;学完这章节&#xff0c;我们将知道写出的代码如何变成可执行程序的&#xff0c;这是非常重要的一个章节&#xff0c;那让我们一起进入本章的学习吧。 本章重点&#xff1a; 程序的翻译环境程序的执行环境详解&#xff1a;C语言程…

周立功ZCANPRO简介和使用

ZCANPRO目录 周立功ZCANPRO简介一、软件安装ZCANPRO官网链接&#xff1a;驱动官网链接 二、ZCANPRO使用1.设备管理2.选择CAN、CANFD波特率计算器使用方法&#xff08;可选&#xff09; 3.新建视图CAN视图DBC视图 4.发送数据普通发送DBC发送 三、高级功能UDS诊断 周立功ZCANPRO简…

【java爬虫】使用selenium获取某交易所公司半年报数据

引言 上市公司的财报数据一般都会进行公开&#xff0c;我们可以在某交易所的官方网站上查看这些数据&#xff0c;由于数据很多&#xff0c;如果只是手动收集的话可能会比较耗时耗力&#xff0c;我们可以采用爬虫的方法进行数据的获取。 本文就介绍采用selenium框架进行公司财…

HTML选项框的设计以及根据不同选项的值对应不同的事件

文章目录 HTML选项框的设计JS根据不同的选项框对应出不同的事件 HTML选项框的设计 在前端页面的设计中&#xff0c;多选框的设计用select标签完成实现 全部选项都显示的选项框 <form><select multiple"multiple"><option></option><opti…

视频怎么压缩?视频过大这样压缩变小

在日常生活中&#xff0c;我们常常会遇到需要压缩视频的情况&#xff0c;视频压缩不仅可以减小文件大小&#xff0c;方便存储和传输&#xff0c;还可以在保证质量的同时&#xff0c;满足不同的使用需求。那么&#xff0c;如何有效地压缩视频呢&#xff1f; 方法一&#xff1a;嗨…

web APIs——第一天(上)

变量声明的时候建议 const优先&#xff0c;尽量使用const 原因&#xff1a; const语义化更好很多变量我们声明的时候就知道他不会被更改了&#xff0c;那为什么不用const呢&#xff1f;实际开发中也是&#xff0c;比如react框架&#xff0c;基本const如果你有纠结的时候&…

python中的yolov5结合PyQt5,使用QT designer设计界面没正确启动的解决方法

python中的yolov5结合PyQt5&#xff0c;使用QT designer设计界面没正确启动的解决方法 一、窗体设计test: 默认你已经设计好了窗体后&#xff1a; 这时你需要的是保存生成的untitle.ui到某个文件夹下&#xff0c;然后在命令行中奖.ui转换为.py&#xff08;&#xff0c;通过​​…

css之Flex弹性布局

文章目录 &#x1f415;前言&#xff1a;&#x1f3e8;定义flex容器 display:flex&#x1f3e8;在flex容器中子组件进行排列&#x1fa82;行排列 flex-direction: row&#x1fa82;将行排列进行翻转排列 flex-direction: row-reverse&#x1f3c5;按列排列 flex-direction: col…

2020年亚太杯APMCM数学建模大赛B题美国总统的经济影响分析求解全过程文档及程序

2020年亚太杯APMCM数学建模大赛 B题 美国总统的经济影响分析 原题再现&#xff1a; 美国总统选举每四年举行一次。 2020年是美国总统大选年&#xff0c;共和党候选人唐纳德特朗普和民主党对手乔拜登竞选总统。 甲乙双方候选人在金融贸易&#xff0c;经济金融治理&#xff0c;…

离散低通滤波方法

低通滤波器允许低频信号通过&#xff0c;并抑制高频信号。其核心思想是在频率域上通过移除高频成分来平滑信号。这在去噪、平滑和提取基本频率成分时非常有用。 离散低通滤波方法通常采用一阶低通滤波器进行处理。一阶低通滤波器是一种常见的数字滤波器&#xff0c;能够将信号…

电脑出现xinput1_3.dll的错误提示怎么办?有什么办法可以解决

电脑如果缺失了xinput1_3.dll还是一件比较复杂的事情&#xff0c;那么电脑出现xinput1_3.dll的错误提示怎么办&#xff0c;又有什么办法可以解决xinput1_3.dll&#xff1f;今天我们就来聊聊xinput1_3.dll丢失的解决办法&#xff0c;来看看都有哪些办法可以解决吧。 一.常见的问…

Leetcode—2331.计算布尔二叉树的值【简单】

2023每日刷题&#xff08;六&#xff09; Leetcode—2331.计算布尔二叉树的值 递归实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ bool evaluateTree(struct TreeNod…

rabbitMQ(3)

RabbitMq 交换机 文章目录 1. 交换机的介绍2. 交换机的类型3. 临时队列4. 绑定 (bindings)5. 扇形交换机&#xff08;Fanout &#xff09; 演示6. 直接交换机 Direct exchange6.1 多重绑定6.2 direct 代码案例 7. 主题交换机7.1 Topic 匹配案例7.2 Topic 代码案例 8. headers 头…