简介:
简单双向二线制,同步串行总线。
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仿真模型。
仿真验证通过,上板验证通过。