• 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时序驱动模块+指令控制模块+按键消抖+顶层;

    1. /************************************************************
    2. **************** iic 模块说明 ************************
    3. **************** 驱动接口模块 ************************
    4. *输入端口:
    5. *sys_clk : 1Mhz时钟信号。
    6. *iic_start : 开始进行读写通信标志信号。
    7. *en_w : 写使能信号,与iic_start同时拉高,iic模块启动写时序。
    8. *addr : 地址信号,读写公用一个地址信号。
    9. *data_w : 要通过iic协议写入从机的8bit数据。
    10. *en_r : 读使能信号,与iic_start同时拉高,iic模块启动读时序。
    11. *addr_num : 由于地址有单byte和双byte情况,addr_num == 0表示单。
    12. *输出端口:
    13. *scl : iic协议的同步时钟信号。串行时钟线,用于同步通讯数据。时钟频率为250kHz
    14. *sda : 双向端口,双向串行数据线。
    15. *data_out : 读取到的1byte数据。
    16. *iic_end : 完成ibyte数据的读写标志信号。
    17. */
    18. module iic (
    19. input wire sys_clk , // 虽然写的是sys_clk但是例化时要接iic_clk
    20. input wire sys_rst_n ,
    21. input wire iic_start ,
    22. input wire en_w ,
    23. input wire en_r ,
    24. input wire [15:0] byte_addr ,
    25. input wire [7:0] data_w ,
    26. input wire addr_num ,
    27. inout wire sda ,
    28. output reg scl ,
    29. output reg [7:0] data_out ,
    30. output reg iic_end
    31. );
    32. // parameter
    33. parameter DEVICE_ADDR = 7'b1010_011 ; // 器件地址,最后一位要根据读写,来决定。[6:0]
    34. wire [7:0] FIRST_ADDR ; // AT24C64
    35. wire [7:0] SECOND_ADDR ; // 可在此设置读写地址。
    36. assign FIRST_ADDR = byte_addr[15:8] ;
    37. assign SECOND_ADDR = byte_addr[ 7:0] ;
    38. // localparam
    39. localparam IDLE =4'b0000 ,
    40. START1 =4'b0001 ,
    41. SEND_DEVICE_ADDR =4'b0011 ,
    42. ACK1 =4'b0010 ,
    43. SEND_FIRST_ADDR =4'b0110 ,
    44. ACK2 =4'b0111 ,
    45. SEND_SECOND_ADDR =4'b0101 ,
    46. ACK3 =4'b0100 ,
    47. WR_DATA =4'b1100 ,
    48. ACK4 =4'b1101 ,
    49. STOP =4'b1111 ,
    50. START2 =4'b1110 ,
    51. SEND_READ_DEVICE_ADDR =4'b1010 ,
    52. ACK5 =4'b1011 ,
    53. READ_DATA =4'b1001 ,
    54. NO_ACK =4'b1000 ;
    55. // wire signal define
    56. wire sda_en ;
    57. wire IDLEtoSTART1 ;
    58. wire START1toSEND_DEVICE_ADDR ;
    59. wire SEND_DEVICE_ADDRtoACK1 ;
    60. wire ACK1toSEND_FIRST_ADDR ;
    61. wire ACK1toSEND_SECOND_ADDR ;
    62. wire SEND_FIRST_ADDRtoACK2 ;
    63. wire ACK2toSEND_SECOND_ADDR ;
    64. wire SEND_SECOND_ADDRtoACK3 ;
    65. wire ACK3toWR_DATA ;
    66. wire ACK3toSTART2 ;
    67. wire WR_DATAtoACK4 ;
    68. wire ACK4toSTOP ;
    69. wire STOPtoIDLE ;
    70. wire START2toSEND_READ_DEVICE_ADDR;
    71. wire SEND_READ_DEVICE_ADDRtoACK5 ;
    72. wire ACK5toREAD_DATA ;
    73. wire READ_DATAtoNO_ACK ;
    74. wire NO_ACKtoSTOP ;
    75. // reg signal define
    76. reg [3:0] state_c ;
    77. reg [3:0] state_n ;
    78. reg [1:0] cnt_iic ; // 关键计数器。很多信号赋值都与他有关。
    79. reg [2:0] cnt_bit ; // bit计数器,计数值0-7
    80. reg sda_out ;
    81. /***********************************************************************/
    82. // 状态机描述
    83. // reg [3:0] state_c ;
    84. always @(posedge sys_clk or negedge sys_rst_n) begin
    85. if(~sys_rst_n)
    86. state_c <= IDLE ;
    87. else
    88. state_c <= state_n ;
    89. end
    90. // reg [3:0] state_n ;
    91. always @(*) begin
    92. case(state_c)
    93. IDLE : if(IDLEtoSTART1)
    94. state_n = START1 ;
    95. else
    96. state_n = IDLE ;
    97. START1 : if(START1toSEND_DEVICE_ADDR)
    98. state_n = SEND_DEVICE_ADDR ;
    99. else
    100. state_n = START1 ;
    101. SEND_DEVICE_ADDR : if(SEND_DEVICE_ADDRtoACK1)
    102. state_n = ACK1 ;
    103. else
    104. state_n = SEND_DEVICE_ADDR ;
    105. ACK1 : if(ACK1toSEND_FIRST_ADDR)
    106. state_n = SEND_FIRST_ADDR ;
    107. else if(ACK1toSEND_SECOND_ADDR)
    108. state_n = SEND_SECOND_ADDR ;
    109. else
    110. state_n = ACK1 ;
    111. SEND_FIRST_ADDR : if(SEND_FIRST_ADDRtoACK2)
    112. state_n = ACK2 ;
    113. else
    114. state_n = SEND_FIRST_ADDR ;
    115. ACK2 : if(ACK2toSEND_SECOND_ADDR)
    116. state_n = SEND_SECOND_ADDR ;
    117. else
    118. state_n = ACK2 ;
    119. SEND_SECOND_ADDR : if(SEND_SECOND_ADDRtoACK3)
    120. state_n = ACK3 ;
    121. else
    122. state_n = SEND_SECOND_ADDR ;
    123. ACK3 : if(ACK3toWR_DATA)
    124. state_n = WR_DATA ;
    125. else if(ACK3toSTART2)
    126. state_n = START2 ;
    127. else
    128. state_n = ACK3 ;
    129. WR_DATA : if(WR_DATAtoACK4)
    130. state_n = ACK4 ;
    131. else
    132. state_n = WR_DATA ;
    133. ACK4 : if(ACK4toSTOP)
    134. state_n = STOP ;
    135. else
    136. state_n = ACK4 ;
    137. STOP : if(STOPtoIDLE)
    138. state_n = IDLE ;
    139. else
    140. state_n = STOP ;
    141. START2 : if(START2toSEND_READ_DEVICE_ADDR)
    142. state_n = SEND_READ_DEVICE_ADDR ;
    143. else
    144. state_n = START2 ;
    145. SEND_READ_DEVICE_ADDR: if(SEND_READ_DEVICE_ADDRtoACK5)
    146. state_n = ACK5 ;
    147. else
    148. state_n = SEND_READ_DEVICE_ADDR ;
    149. ACK5 : if(ACK5toREAD_DATA)
    150. state_n = READ_DATA ;
    151. else
    152. state_n = ACK5 ;
    153. READ_DATA : if(READ_DATAtoNO_ACK)
    154. state_n = NO_ACK ;
    155. else
    156. state_n = READ_DATA ;
    157. NO_ACK : if(NO_ACKtoSTOP)
    158. state_n = STOP ;
    159. else
    160. state_n = NO_ACK ;
    161. default : state_n = IDLE ;
    162. endcase
    163. end
    164. // 状态转移条件赋值:
    165. assign IDLEtoSTART1 = (state_c == IDLE ) && (iic_start == 1'b1) ;
    166. assign START1toSEND_DEVICE_ADDR = (state_c == START1) && (cnt_iic == 3) ;
    167. assign SEND_DEVICE_ADDRtoACK1 = (state_c == SEND_DEVICE_ADDR) && (cnt_iic == 3 && cnt_bit == 7) ;
    168. assign ACK1toSEND_FIRST_ADDR = (state_c == ACK1 ) && (cnt_iic == 3 && sda == 1'b0 && addr_num == 1) ; //&& sda == 1'b0 由于仿真模型没有相应ack功能,所以要自己模拟。
    169. assign ACK1toSEND_SECOND_ADDR = (state_c == ACK2 ) && (cnt_iic == 3 && sda == 1'b0 && addr_num == 0) ; //&& sda == 1'b0
    170. assign SEND_FIRST_ADDRtoACK2 = (state_c == SEND_FIRST_ADDR) && (cnt_iic == 3 && cnt_bit == 7) ;
    171. assign ACK2toSEND_SECOND_ADDR = (state_c == ACK2 ) && (cnt_iic == 3 && sda == 0) ; //&& sda == 0
    172. assign SEND_SECOND_ADDRtoACK3 = (state_c == SEND_SECOND_ADDR) && (cnt_iic == 3 && cnt_bit == 7) ;
    173. assign ACK3toWR_DATA = (state_c == ACK3 ) && (cnt_iic == 3 && en_w && sda == 0) ; // && sda == 0
    174. assign ACK3toSTART2 = (state_c == ACK3 ) && (cnt_iic == 3 && en_r && sda == 0) ; // && sda == 0
    175. assign WR_DATAtoACK4 = (state_c == WR_DATA ) && (cnt_iic == 3 && cnt_bit == 7) ;
    176. assign ACK4toSTOP = (state_c == ACK4 ) && (cnt_iic == 3 && sda == 0) ; // && sda == 0
    177. assign STOPtoIDLE = (state_c == STOP ) && (cnt_iic == 3 && cnt_bit == 3) ;
    178. assign START2toSEND_READ_DEVICE_ADDR = (state_c == START2) && (cnt_iic == 3) ;
    179. assign SEND_READ_DEVICE_ADDRtoACK5 = (state_c == SEND_READ_DEVICE_ADDR) && (cnt_iic == 3 && cnt_bit == 7) ;
    180. assign ACK5toREAD_DATA = (state_c == ACK5 ) && (cnt_iic == 3 && sda == 0) ; //&& sda == 0
    181. assign READ_DATAtoNO_ACK = (state_c == READ_DATA) && (cnt_iic == 3 && cnt_bit == 7) ;
    182. assign NO_ACKtoSTOP = (state_c == NO_ACK) && (cnt_iic == 3 && sda == 1) ;
    183. // reg [1:0] cnt_iic ; // 关键计数器。很多信号赋值都与他有关。
    184. always @(posedge sys_clk or negedge sys_rst_n) begin
    185. if(~sys_rst_n)
    186. cnt_iic <= 2'd0 ;
    187. else if(state_c != IDLE)
    188. cnt_iic <= cnt_iic + 1'b1 ;
    189. else
    190. cnt_iic <= 1'b0 ;
    191. end
    192. // reg [2:0] cnt_bit ; // bit计数器,计数值0-7
    193. always @(posedge sys_clk or negedge sys_rst_n) begin
    194. if(~sys_rst_n)
    195. cnt_bit <= 3'd0 ;
    196. 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)
    197. cnt_bit <= cnt_bit + 1'b1 ;
    198. 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)
    199. cnt_bit <= cnt_bit ;
    200. else
    201. cnt_bit <= 3'd0 ;
    202. end
    203. // reg sda_out ;
    204. always @(posedge sys_clk or negedge sys_rst_n) begin
    205. if(~sys_rst_n)
    206. sda_out <= 1'b1 ;
    207. else
    208. case (state_c)
    209. IDLE : sda_out <= 1'b1 ;
    210. START1 : if(cnt_iic == 0)
    211. sda_out <= 1'b0 ;
    212. else
    213. sda_out <= sda_out ;
    214. SEND_DEVICE_ADDR : if(cnt_iic == 0 && cnt_bit != 7)
    215. sda_out <= DEVICE_ADDR[6 - cnt_bit] ;
    216. else if(cnt_iic == 0 && cnt_bit == 7)
    217. sda_out <= 1'b0 ; // 写控制位。
    218. ACK1 : sda_out <= 1'b0 ;
    219. SEND_FIRST_ADDR : if(cnt_iic == 0)
    220. sda_out <= FIRST_ADDR[7 - cnt_bit] ;
    221. else
    222. sda_out <= sda_out ;
    223. ACK2 : sda_out <= 1'b0 ;
    224. SEND_SECOND_ADDR : if(cnt_iic == 0)
    225. sda_out <= SECOND_ADDR[7 - cnt_bit] ;
    226. else
    227. sda_out <= sda_out ;
    228. ACK3 : sda_out <= 1'b0 ;
    229. WR_DATA : if(cnt_iic == 0)
    230. sda_out <= data_w[7 - cnt_bit] ;
    231. else
    232. sda_out <= sda_out ;
    233. ACK4 : sda_out <= 1'b0 ;
    234. STOP : if(cnt_iic == 0 && cnt_bit == 0)
    235. sda_out <= 1'b0 ;
    236. else if(cnt_iic == 2 && cnt_bit == 0)
    237. sda_out <= 1'b1 ;
    238. else
    239. sda_out <= sda_out ;
    240. START2 : if(cnt_iic == 0)
    241. sda_out <= 1'b1 ;
    242. else if(cnt_iic == 2)
    243. sda_out <= 1'b0 ;
    244. else
    245. sda_out <= sda_out ;
    246. SEND_READ_DEVICE_ADDR: if(cnt_iic == 0 && cnt_bit != 7)
    247. sda_out <= DEVICE_ADDR[6 - cnt_bit] ;
    248. else if(cnt_iic == 0 && cnt_bit == 7)
    249. sda_out <= 1'b1 ; // 读控制位。
    250. ACK5 : sda_out <= 1'b0 ;
    251. READ_DATA : sda_out <= 1'b0 ;
    252. NO_ACK : sda_out <= 1'b1 ;
    253. default : sda_out <= 1'b1 ;
    254. endcase
    255. end
    256. // wire sda_en
    257. 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 ;
    258. /***************************************************************************/
    259. // wire sda ,
    260. assign sda = (sda_en == 1) ? sda_out : 1'bz ;
    261. // reg scl ,
    262. always @(posedge sys_clk or negedge sys_rst_n) begin
    263. if(~sys_rst_n)
    264. scl <= 1'b1 ;
    265. else
    266. if(state_c != IDLE && state_c != STOP && state_c != START1) begin
    267. if(cnt_iic == 1 || cnt_iic == 3)
    268. scl <= ~scl ;
    269. else
    270. scl <= scl ;
    271. end
    272. else if(state_c == IDLE)
    273. scl <= 1'b1 ;
    274. else if(state_c == STOP && (cnt_bit == 0 && cnt_iic == 1))
    275. scl <= 1'b1 ;
    276. else if(state_c == STOP)
    277. scl <= scl ;
    278. else if(state_c == START1 && cnt_iic == 3)
    279. scl <= ~scl ;
    280. else if(state_c == START1)
    281. scl <= scl ;
    282. else
    283. scl <= 1'b1 ;
    284. end
    285. // reg sda_data ;
    286. // always @(posedge sys_clk or negedge sys_rst_n) begin
    287. // if(~sys_rst_n)
    288. // sda_data <= 1'b0 ;
    289. // else if(state_c == READ_DATA && cnt_iic == 0)
    290. // sda_data <= ~sda_data ;
    291. // else
    292. // sda_data <= sda_data ;
    293. // end
    294. // reg [7:0] data_out
    295. always @(posedge sys_clk or negedge sys_rst_n) begin
    296. if(~sys_rst_n)
    297. data_out <= 8'd0 ;
    298. else if(state_c == READ_DATA && cnt_iic == 2 && scl == 1)
    299. data_out <= {data_out[6:0],sda} ; // 这里也需要自己模拟 sda_data
    300. else
    301. data_out <= data_out ;
    302. end
    303. // wire iic_end
    304. always @(posedge sys_clk or negedge sys_rst_n) begin
    305. if(~sys_rst_n)
    306. iic_end <= 1'b0 ;
    307. else if(state_c == STOP && cnt_iic == 3 && cnt_bit == 3)
    308. iic_end <= 1'b1 ;
    309. else
    310. iic_end <= 1'b0 ;
    311. end
    312. endmodule
    1. /************************************************************
    2. **************** iic_instruct 模块说明 ************************
    3. **************** 产生接口时序模块的控制信号,并存储读到的数据,并把数据传给数码管显示模块。
    4. */
    5. module iic_instruct (
    6. input wire sys_clk , // 20ns
    7. input wire sys_rst_n ,
    8. input wire iic_clk , // 1000ns
    9. input wire flag_w ,
    10. input wire flag_r ,
    11. input wire iic_end ,
    12. input wire [7:0] data_r , // iic 模块读到的1byte数据。
    13. output reg iic_start ,
    14. output reg en_w , // 写使能,往eeprom中写数据的使能信号。
    15. output reg en_r , // 读使能,从eeprom中读数据的使能信号。
    16. output reg [15:0] byte_addr , // 读写操作的数据地址。
    17. output reg [7:0] data_w , // 往eeprom中写入的数据。
    18. output wire addr_num , // eeprom的存储地址是几个byte。
    19. output wire [7:0] data_out // 传给数码管显示的数据。
    20. );
    21. parameter ADDR_START = 16'h00_00 ,
    22. DATA_WRITE = 8'd00 , // 写入的起始数据。
    23. CNT_MAX_START = 49999 , // 5ms
    24. CNT_MAX_1S = 1_000_000 ,
    25. CNT_MAX_WRITE_BYTE = 10 ,
    26. CNT_MAX_READ_BYTE = 10 ;
    27. /******************************************************/
    28. // 第一步:处理输入信号,实现快速时钟域标志信号同步到慢速时钟域。
    29. // 也就是保证慢速时钟域可以检测到标志信号。
    30. reg valid_write ;
    31. reg [7:0] cnt_write ;
    32. reg valid_read ;
    33. reg [7:0] cnt_read ;
    34. reg [15:0] cnt_read_byte ;
    35. reg [15:0] cnt_start ;
    36. reg [15:0] cnt_write_byte ; // 写入eeprom字节计数器
    37. wire empty ;
    38. wire full ;
    39. wire [9:0] usedw ;
    40. always @(posedge sys_clk or negedge sys_rst_n) begin
    41. if(~sys_rst_n)
    42. valid_write <= 1'b0 ;
    43. else if(flag_w)
    44. valid_write <= 1'b1 ;
    45. else if(cnt_write == 199)
    46. valid_write <= 1'b0 ;
    47. else
    48. valid_write <= valid_write ;
    49. end
    50. always @(posedge sys_clk or negedge sys_rst_n) begin
    51. if(~sys_rst_n)
    52. cnt_write <= 8'd0 ;
    53. else if(valid_write && cnt_write == 199)
    54. cnt_write <= 8'd0 ;
    55. else if(valid_write)
    56. cnt_write <= cnt_write + 1'b1 ;
    57. else
    58. cnt_write <= 8'd0 ;
    59. end
    60. always @(posedge sys_clk or negedge sys_rst_n) begin
    61. if(~sys_rst_n)
    62. valid_read <= 1'b0 ;
    63. else if(flag_r)
    64. valid_read <= 1'b1 ;
    65. else if(cnt_read == 199)
    66. valid_read <= 1'b0 ;
    67. else
    68. valid_read <= valid_read ;
    69. end
    70. always @(posedge sys_clk or negedge sys_rst_n) begin
    71. if(~sys_rst_n)
    72. cnt_read <= 8'd0 ;
    73. else if(valid_read && cnt_read == 199)
    74. cnt_read <= 8'd0 ;
    75. else if(valid_read)
    76. cnt_read <= cnt_read + 1'b1 ;
    77. else
    78. cnt_read <= 8'd0 ;
    79. end
    80. assign addr_num = 1'b1 ;
    81. /**********************************************************************************/
    82. // 第二步:产生写数据相关信号的产生。在iic_clk时钟域下。
    83. // en_w
    84. always @(posedge iic_clk or negedge sys_rst_n) begin
    85. if(~sys_rst_n)
    86. en_w <= 1'b0 ;
    87. else if(iic_end && (cnt_write_byte == CNT_MAX_WRITE_BYTE - 1))
    88. en_w <= 1'b0 ;
    89. else if(valid_write)
    90. en_w <= 1'b1 ;
    91. else
    92. en_w <= en_w ;
    93. end
    94. //reg iic_start
    95. always @(posedge iic_clk or negedge sys_rst_n) begin
    96. if(~sys_rst_n)
    97. iic_start <= 1'b0 ;
    98. else if(en_w == 0 && valid_write == 1 || cnt_start == CNT_MAX_START - 1)
    99. iic_start <= 1'b1 ;
    100. else
    101. iic_start <= 1'b0 ;
    102. end
    103. // reg [15:0] cnt_start ;
    104. always @(posedge iic_clk or negedge sys_rst_n) begin
    105. if(~sys_rst_n)
    106. cnt_start <= 16'd0 ;
    107. else if(((en_w == 1) && ((cnt_start == CNT_MAX_START - 1)
    108. || (iic_end == 1 && cnt_write_byte == CNT_MAX_WRITE_BYTE - 1)))
    109. || ((en_r == 1) && ((cnt_start == CNT_MAX_START - 1)
    110. || (iic_end == 1 && cnt_read_byte == CNT_MAX_READ_BYTE - 1))))
    111. cnt_start <= 16'd0 ;
    112. else if(en_w == 1 || en_r)
    113. cnt_start <= cnt_start + 1'b1 ;
    114. else
    115. cnt_start <= 16'd0 ;
    116. end
    117. // [15:0] byte_addr // 目前只完成了写地址,
    118. always @(posedge iic_clk or negedge sys_rst_n) begin
    119. if(~sys_rst_n)
    120. byte_addr <= ADDR_START ;
    121. else if((iic_end == 1 && cnt_write_byte == CNT_MAX_WRITE_BYTE - 1)
    122. || (iic_end == 1 && cnt_read_byte == CNT_MAX_READ_BYTE - 1))
    123. byte_addr <= ADDR_START ;
    124. else if(iic_end == 1)
    125. byte_addr <= byte_addr + 1'b1 ;
    126. else
    127. byte_addr <= byte_addr ;
    128. end
    129. // [7:0] data_w
    130. always @(posedge iic_clk or negedge sys_rst_n) begin
    131. if(~sys_rst_n)
    132. data_w <= DATA_WRITE ;
    133. else if(iic_end == 1 && cnt_write_byte == CNT_MAX_WRITE_BYTE - 1)
    134. data_w <= DATA_WRITE ;
    135. else if(en_w && iic_end == 1)
    136. data_w <= data_w + 1'b1 ;
    137. else
    138. data_w <= data_w ;
    139. end
    140. // [15:0] cnt_write_byte
    141. always @(posedge iic_clk or negedge sys_rst_n) begin
    142. if(~sys_rst_n)
    143. cnt_write_byte <= 16'd0 ;
    144. else if(en_w && iic_end == 1 && cnt_write_byte == CNT_MAX_WRITE_BYTE - 1)
    145. cnt_write_byte <= 16'd0 ;
    146. else if(en_w && iic_end == 1)
    147. cnt_write_byte <= cnt_write_byte + 1'b1 ;
    148. else
    149. cnt_write_byte <= cnt_write_byte ;
    150. end
    151. /*****************************************************************************/
    152. // 读相关控制信号产生
    153. // en_r
    154. always @(posedge iic_clk or negedge sys_rst_n) begin
    155. if(~sys_rst_n)
    156. en_r <= 1'b0 ;
    157. else if(iic_end == 1 && cnt_read_byte == CNT_MAX_READ_BYTE - 1)
    158. en_r <= 1'b0 ;
    159. else if(valid_read)
    160. en_r <= 1'b1 ;
    161. else
    162. en_r <= en_r ;
    163. end
    164. // [15:0] cnt_read_byte
    165. always @(posedge iic_clk or negedge sys_rst_n) begin
    166. if(~sys_rst_n)
    167. cnt_read_byte <= 16'd0 ;
    168. else if(en_r && iic_end == 1 && cnt_read_byte == CNT_MAX_READ_BYTE - 1)
    169. cnt_read_byte <= 16'd0 ;
    170. else if(en_r && iic_end == 1)
    171. cnt_read_byte <= cnt_read_byte + 1'b1 ;
    172. else
    173. cnt_read_byte <= cnt_read_byte ;
    174. end
    175. /*******************************************************************************/
    176. reg valid_fifo_read ;
    177. reg [19:0] cnt_1s ;
    178. reg fifo_rd_en ;
    179. // valid_fifo_read
    180. always @(posedge iic_clk or negedge sys_rst_n) begin
    181. if(~sys_rst_n)
    182. valid_fifo_read <= 1'b0 ;
    183. else if(valid_fifo_read == 1 && usedw == 0)
    184. valid_fifo_read <= 1'b0 ;
    185. else if(usedw > (CNT_MAX_READ_BYTE - 1))
    186. valid_fifo_read <= 1'b1 ;
    187. else
    188. valid_fifo_read <= valid_fifo_read ;
    189. end
    190. // [19:0] cnt_1s
    191. always @(posedge iic_clk or negedge sys_rst_n) begin
    192. if(~sys_rst_n)
    193. cnt_1s <= 20'd0 ;
    194. else if(valid_fifo_read == 1 && cnt_1s == CNT_MAX_1S - 1)
    195. cnt_1s <= 20'd0 ;
    196. else if(valid_fifo_read == 1)
    197. cnt_1s <= cnt_1s + 1'b1 ;
    198. else
    199. cnt_1s <= 20'd0 ;
    200. end
    201. // fifo_rd_en
    202. always @(posedge iic_clk or negedge sys_rst_n) begin
    203. if(~sys_rst_n)
    204. fifo_rd_en <= 1'b0 ;
    205. else if(valid_fifo_read == 1 && cnt_1s == CNT_MAX_1S - 1)
    206. fifo_rd_en <= 1'b1 ;
    207. else
    208. fifo_rd_en <= 1'b0 ;
    209. end
    210. fifo_8x1024 fifo_8x1024_inst(
    211. .clock ( iic_clk ) ,
    212. .data ( data_r ) ,
    213. .rdreq ( fifo_rd_en ) ,
    214. .wrreq ( en_r && iic_end ) ,
    215. .empty ( empty ) ,
    216. .full ( full ) ,
    217. .q ( data_out ) ,
    218. .usedw ( usedw )
    219. );
    220. endmodule

     

    1. module top (
    2. input wire sys_clk ,
    3. input wire sys_rst_n ,
    4. input wire key_write ,
    5. input wire key_read ,
    6. inout wire sda ,
    7. output wire scl ,
    8. output wire ds ,
    9. output wire oe ,
    10. output wire shcp ,
    11. output wire stcp
    12. );
    13. // 例化间连线
    14. wire clk_50mHz ;
    15. wire clk_1mHz ;
    16. wire locked ;
    17. wire rst_n ;
    18. wire flag_write ;
    19. wire flag_read ;
    20. wire [05:00] point ;
    21. wire sign ;
    22. assign point = 5'd0 ;
    23. assign sign = 1'b0 ;
    24. assign rst_n = sys_rst_n && locked ;
    25. pll pll_isnt(
    26. .areset ( ~sys_rst_n ) ,
    27. .inclk0 ( sys_clk ) ,
    28. .c0 ( clk_50mHz ) ,
    29. .c1 ( clk_1mHz ) ,
    30. .locked ( locked )
    31. );
    32. key_filter key_filter_inst_w(
    33. .sys_clk ( clk_50mHz ) ,
    34. .sys_rst_n ( rst_n ) ,
    35. .key_in ( key_write ) ,
    36. .key_out ( flag_write)
    37. );
    38. key_filter key_filter_inst_r(
    39. .sys_clk ( clk_50mHz ) ,
    40. .sys_rst_n ( rst_n ) ,
    41. .key_in ( key_read ) ,
    42. .key_out ( flag_read )
    43. );
    44. wire iic_start ;
    45. wire en_w ;
    46. wire en_r ;
    47. wire [15:0] byte_addr ;
    48. wire [7:0] data_w ;
    49. wire addr_num ;
    50. wire [7:0] data_out ;
    51. wire iic_end ;
    52. wire [7:0] data_r ;
    53. iic_instruct iic_instruct_inst(
    54. .sys_clk ( clk_50mHz ) , // 20ns
    55. .sys_rst_n ( rst_n ) ,
    56. .iic_clk ( clk_1mHz ) , // 1000ns
    57. .flag_w ( flag_write ) ,
    58. .flag_r ( flag_read ) ,
    59. .iic_end ( iic_end ) ,
    60. .data_r ( data_r ) , // iic 模块读到的1byte数据。
    61. .iic_start ( iic_start ) ,
    62. .en_w ( en_w ) , // 写使能,往eeprom中写数据的使能信号。
    63. .en_r ( en_r ) , // 读使能,从eeprom中读数据的使能信号。
    64. .byte_addr ( byte_addr ) , // 读写操作的数据地址。
    65. .data_w ( data_w ) , // 往eeprom中写入的数据。
    66. .addr_num ( addr_num ) , // eeprom的存储地址是几个byte。
    67. .data_out ( data_out ) // 传给数码管显示的数据。
    68. );
    69. iic iic_inst(
    70. .sys_clk ( clk_1mHz ) , // 虽然写的是sys_clk但是例化时要接iic_clk
    71. .sys_rst_n ( rst_n ) ,
    72. .iic_start ( iic_start ) ,
    73. .en_w ( en_w ) ,
    74. .en_r ( en_r ) ,
    75. .byte_addr ( byte_addr ) ,
    76. .data_w ( data_w ) ,
    77. .addr_num ( addr_num ) ,
    78. .sda ( sda ) ,
    79. .scl ( scl ) ,
    80. .data_out ( data_r ) ,
    81. .iic_end ( iic_end )
    82. );
    83. seg_595_dynamic seg_595_dynamic_isnt(
    84. .sys_clk ( clk_50mHz ) ,
    85. .sys_rst_n ( rst_n ) ,
    86. .data ( {12'd0,data_out} ) ,
    87. .point ( point ) ,
    88. .sign ( sign ) ,
    89. .seg_en ( rst_n ) ,
    90. .ds ( ds ) ,
    91. .oe ( oe ) ,
    92. .shcp ( shcp ) ,
    93. .stcp ( stcp )
    94. );
    95. endmodule

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

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

  • 相关阅读:
    【网络知识必知必会】再谈Cookie和Session
    java毕业设计点播影院运营系统mybatis+源码+调试部署+系统+数据库+lw
    Spring 最常用的几个注解
    在T3开发板上实现SylixOS最小系统(五)——实现T3串口驱动开发
    RocketMQ简介与安装
    概念解析 | 揭秘视觉与语言交叉模型:CLIP和BLIP的介绍
    vulnhub靶机Os-hackNos-1
    【华为OD机试真题 python】贪吃蛇【2022 Q4 | 200分】
    【Unity3D】GUI控件
    最新AI智能聊天对话问答系统源码(详细图文搭建部署教程)+AI绘画系统,DALL-E3文生图, Whisper & TTS 语音识别,文档分析
  • 原文地址:https://blog.csdn.net/Meng_long2022/article/details/133933491