• FPGA project : flash_secter_erase


    flash的指定扇区擦除实验。

    先发写指令,再进入写锁存周期等待500ns,进入写扇区擦除指令,然后写扇区地址,页地址,字节地址。即可完成扇区擦除。

    模块框图:

    时序图: 

    代码: 

    1. module spi (
    2. input wire sys_clk ,
    3. input wire sys_rst_n ,
    4. input wire key_start ,
    5. output wire miso ,
    6. output reg mosi ,
    7. output reg cs_n ,
    8. output reg sck
    9. );
    10. // parameter
    11. parameter COMD_W = 8'h06 , // 写指令
    12. COMD_B = 8'hc7 , // 全擦除指令
    13. COMD_S = 8'hd8 ; // 扇区擦除指令
    14. parameter ADR_SE = 8'h00 , // 扇区地址 adress secter
    15. ADR_PA = 8'h04 , // 页地址 adress page
    16. ADR_BY = 8'h25 ; // 字节地址 adress byte
    17. parameter IDLE = 4'b0001 ,
    18. WREN = 4'b0010 ,
    19. WEL = 4'b0100 ,
    20. SE = 4'b1000 ;
    21. // wire signal degine
    22. wire IDLEtoWREN;
    23. wire WRENtoWEL ;
    24. wire WRENtoSE ;
    25. wire SEtoIDLE ;
    26. // reg signal define
    27. reg [3:0] state_c ;
    28. reg [3:0] state_n ;
    29. reg [3:0] cnt_20ns ;
    30. reg [3:0] cnt_bit ;
    31. reg [3:0] cnt_byte ;
    32. reg flag_bit ;
    33. reg f_b_reg ; // flag_bit_reg的缩写
    34. /****************************************************************************/
    35. // 三段式状态机
    36. // 现态与次态描述
    37. // state_c
    38. always @(posedge sys_clk or negedge sys_rst_n) begin
    39. if(~sys_rst_n)
    40. state_c <= IDLE ;
    41. else
    42. state_c <= state_n ;
    43. end
    44. // state_n
    45. always @(*) begin
    46. case (state_c)
    47. IDLE :if(IDLEtoWREN)
    48. state_n <= WREN ;
    49. else
    50. state_n <= IDLE ;
    51. WREN :if(WRENtoWEL)
    52. state_n <= WEL ;
    53. else
    54. state_n <= WREN ;
    55. WEL :if(WRENtoSE)
    56. state_n <= SE ;
    57. else
    58. state_n <= WEL ;
    59. SE :if(SEtoIDLE)
    60. state_n <= IDLE ;
    61. else
    62. state_n <= SE ;
    63. default: state_n <= IDLE ;
    64. endcase
    65. end
    66. // 状态转移描述
    67. assign IDLEtoWREN = ( state_c == IDLE) && ( key_start ) ;
    68. assign WRENtoWEL = ( state_c == WREN) && ( f_b_reg ) ;
    69. assign WRENtoSE = ( state_c == WEL ) && ( cnt_20ns == 6 ) ;
    70. assign SEtoIDLE = ( state_c == SE ) && ( f_b_reg ) ;
    71. // 相关信号描述
    72. // reg [3:0] cnt_20ns ;
    73. always @(posedge sys_clk or negedge sys_rst_n) begin
    74. if(~sys_rst_n)
    75. cnt_20ns <= 4'd0 ;
    76. else
    77. case (state_c)
    78. IDLE : cnt_20ns <= 4'd0 ;
    79. WREN : if(cnt_20ns || f_b_reg)
    80. cnt_20ns <= 4'd0 ;
    81. else
    82. cnt_20ns <= cnt_20ns + 1'b1 ;
    83. WEL : if(cnt_20ns == 6) // 60x20ns==120ns
    84. cnt_20ns <= 4'd0 ;
    85. else
    86. cnt_20ns <= cnt_20ns + 1'b1 ;
    87. SE : if(cnt_20ns || f_b_reg)
    88. cnt_20ns <= 4'd0 ;
    89. else
    90. cnt_20ns <= cnt_20ns + 1'b1 ;
    91. default: cnt_20ns <= 4'd0 ;
    92. endcase
    93. end
    94. // reg [3:0] cnt_bit ;
    95. always @(posedge sys_clk or negedge sys_rst_n) begin
    96. if(~sys_rst_n)
    97. cnt_bit <= 4'd0 ;
    98. else
    99. case (state_c)
    100. IDLE : cnt_bit <= 4'd0 ;
    101. WREN : if(!cnt_20ns && sck && cnt_bit == 7)
    102. cnt_bit <= 4'd0 ;
    103. else if(!cnt_20ns && sck)
    104. cnt_bit <= cnt_bit + 1'b1 ;
    105. WEL : cnt_bit <= 4'd0 ;
    106. SE : if(!cnt_20ns && sck && cnt_bit == 7)
    107. cnt_bit <= 4'd0 ;
    108. else if(!cnt_20ns && sck)
    109. cnt_bit <= cnt_bit + 1'b1 ;
    110. default: cnt_bit <= 4'd0 ;
    111. endcase
    112. end
    113. // reg [3:0] cnt_byte
    114. always @(posedge sys_clk or negedge sys_rst_n) begin
    115. if(~sys_rst_n)
    116. cnt_byte <= 4'd0 ;
    117. else if(cnt_bit == 7 && !cnt_20ns && sck && cnt_byte == 4)
    118. cnt_byte <= 4'd0 ;
    119. else if(cnt_bit == 7 && !cnt_20ns && sck)
    120. cnt_byte <= cnt_byte + 1'b1 ;
    121. else
    122. cnt_byte <= cnt_byte ;
    123. end
    124. // reg flag_bit ;
    125. always @(posedge sys_clk or negedge sys_rst_n) begin
    126. if(~sys_rst_n)
    127. flag_bit <= 1'b0 ;
    128. else
    129. case (state_c)
    130. IDLE : flag_bit <= 1'b0 ;
    131. WREN : if(cnt_bit == 7 && sck && !cnt_20ns)
    132. flag_bit <= 1'b1 ;
    133. else
    134. flag_bit <= flag_bit ;
    135. WEL : flag_bit <= 1'b0 ;
    136. SE : if(cnt_bit == 7 && sck && !cnt_20ns && cnt_byte == 4)
    137. flag_bit <= 1'b1 ;
    138. else
    139. flag_bit <= flag_bit ;
    140. default: flag_bit <= 1'b0 ;
    141. endcase
    142. end
    143. // reg f_b_reg ;
    144. always @(posedge sys_clk or negedge sys_rst_n) begin
    145. if(~sys_rst_n) begin
    146. f_b_reg <= 1'b0 ;
    147. end else begin
    148. f_b_reg <= flag_bit ;
    149. end
    150. end
    151. // output signal
    152. // wire miso ,
    153. assign miso = 1'bz ;
    154. // mosi
    155. always @(posedge sys_clk or negedge sys_rst_n) begin
    156. if(~sys_rst_n)
    157. mosi <= 1'b0 ;
    158. else
    159. case (state_c)
    160. IDLE : mosi <= 1'b0 ;
    161. WREN : if(!cnt_bit) // (cnt_bit == 0)
    162. mosi <= COMD_W[7] ;
    163. else if(cnt_20ns && sck)
    164. mosi <= COMD_W[7 - cnt_bit] ;
    165. else
    166. mosi <= mosi ;
    167. WEL : mosi <= 1'b0 ;
    168. SE : case (cnt_byte)
    169. 1:
    170. begin
    171. if(!cnt_bit)
    172. mosi <= COMD_S[7] ;
    173. else if(cnt_20ns && sck)
    174. mosi <= COMD_S[7 - cnt_bit] ;
    175. else
    176. mosi <= mosi ;
    177. end
    178. 2:
    179. begin
    180. if(!cnt_bit)
    181. mosi <= ADR_SE[7] ;
    182. else if(cnt_20ns && sck)
    183. mosi <= ADR_SE[7 - cnt_bit] ;
    184. else
    185. mosi <= mosi ;
    186. end
    187. 3:
    188. begin
    189. if(!cnt_bit)
    190. mosi <= ADR_PA[7] ;
    191. else if(cnt_20ns && sck)
    192. mosi <= ADR_PA[7 - cnt_bit] ;
    193. else
    194. mosi <= mosi ;
    195. end
    196. 4:
    197. begin
    198. if(!cnt_bit)
    199. mosi <= ADR_BY[7] ;
    200. else if(cnt_20ns && sck)
    201. mosi <= ADR_BY[7 - cnt_bit] ;
    202. else
    203. mosi <= mosi ;
    204. end
    205. default: mosi <= 1'b0 ;
    206. endcase
    207. default: mosi <= 1'b0 ;
    208. endcase
    209. end
    210. // reg cs_n ,
    211. always @(posedge sys_clk or negedge sys_rst_n) begin
    212. if(~sys_rst_n) begin
    213. cs_n <= 1'b1 ;
    214. end else begin
    215. case (state_c)
    216. IDLE : if(key_start)
    217. cs_n <= 1'b0 ;
    218. else
    219. cs_n <= 1'b1 ;
    220. WREN : if(f_b_reg)
    221. cs_n <= 1'b1 ;
    222. else
    223. cs_n <= cs_n ;
    224. WEL : if(cnt_20ns == 6)
    225. cs_n <= 1'b0 ;
    226. else
    227. cs_n <= cs_n ;
    228. SE : if(f_b_reg)
    229. cs_n <= 1'b1 ;
    230. else
    231. cs_n <= cs_n ;
    232. default: cs_n <= 1'b1 ;
    233. endcase
    234. end
    235. end
    236. // reg sck
    237. always @(posedge sys_clk or negedge sys_rst_n) begin
    238. if(~sys_rst_n)
    239. sck <= 1'b0 ;
    240. else
    241. case (state_c)
    242. IDLE : sck <= 1'b0 ;
    243. WREN : if(cnt_20ns)
    244. sck <= ~sck ;
    245. else
    246. sck <= sck ;
    247. WEL : sck <= 1'b0 ;
    248. SE : if(cnt_20ns)
    249. sck <= ~sck ;
    250. else
    251. sck <= sck ;
    252. default: sck <= 1'b0 ;
    253. endcase
    254. end
    255. endmodule
    1. module top(
    2. input wire sys_clk ,
    3. input wire sys_rst_n ,
    4. input wire key_in ,
    5. output wire cs_n ,
    6. output wire sck ,
    7. output wire mosi
    8. );
    9. // 例化间连线
    10. wire key_flag ;
    11. key_filter key_filter_inst(
    12. .sys_clk ( sys_clk ) ,
    13. .sys_rst_n ( sys_rst_n ) ,
    14. .key_in ( key_in ) ,
    15. .key_out ( key_flag )
    16. );
    17. spi spi_inst(
    18. .sys_clk ( sys_clk ) ,
    19. .sys_rst_n ( sys_rst_n ) ,
    20. .key_start ( key_flag ) ,
    21. .mosi ( mosi ) ,
    22. .miso ( ) ,
    23. .cs_n ( cs_n ) ,
    24. .sck ( sck )
    25. );endmodule
    1. module key_filter
    2. #(
    3. parameter MAX_CNT_20MS = 20'd100_0000
    4. )(
    5. input wire sys_clk ,
    6. input wire sys_rst_n ,
    7. input wire key_in ,
    8. output wire key_out
    9. );
    10. reg key_r_0 ;
    11. reg key_r_1 ;
    12. wire nege ;
    13. wire pose ;
    14. reg [19:00] cnt_20ms ;
    15. wire add_cnt_20ms ;
    16. wire end_cnt_20ms ;
    17. reg add_cnt_flag ;
    18. // key_r_0 key_r_1
    19. always @(posedge sys_clk or negedge sys_rst_n) begin
    20. if(~sys_rst_n) begin
    21. key_r_0 <= 1'b1 ;
    22. end else begin
    23. key_r_0 <= key_in ;
    24. end
    25. end
    26. always @(posedge sys_clk or negedge sys_rst_n) begin
    27. if(~sys_rst_n) begin
    28. key_r_1 <= 1'b1 ;
    29. end else begin
    30. key_r_1 <= key_r_0 ;
    31. end
    32. end
    33. // nege pose
    34. assign nege = ~key_r_0 && key_r_1 ;
    35. assign pose = key_r_0 && ~key_r_1 ;
    36. // add_cnt_flag
    37. always @(posedge sys_clk or negedge sys_rst_n) begin
    38. if(~sys_rst_n) begin
    39. add_cnt_flag <= 1'b0 ;
    40. end else begin
    41. if(nege) begin
    42. add_cnt_flag <= 1'b1 ;
    43. end else begin
    44. if( pose || end_cnt_20ms ) begin
    45. add_cnt_flag <= 1'b0 ;
    46. end else begin
    47. add_cnt_flag <= add_cnt_flag ;
    48. end
    49. end
    50. end
    51. end
    52. // cnt_20ms add_cnt_20ms end_cnt_20ms
    53. always @(posedge sys_clk or negedge sys_rst_n) begin
    54. if(~sys_rst_n) begin
    55. cnt_20ms <= 20'd0 ;
    56. end else begin
    57. if(add_cnt_20ms) begin
    58. if(end_cnt_20ms) begin
    59. cnt_20ms <= 20'd0 ;
    60. end else begin
    61. cnt_20ms <= cnt_20ms + 20'd1 ;
    62. end
    63. end else begin
    64. cnt_20ms <= 20'd0 ;
    65. end
    66. end
    67. end
    68. assign add_cnt_20ms = add_cnt_flag ;
    69. assign end_cnt_20ms = add_cnt_20ms && cnt_20ms == ( MAX_CNT_20MS - 1'b1 ) ;
    70. // key_out
    71. // always @(posedge sys_clk or negedge sys_rst_n) begin
    72. // // always @(*) begin // 这样的话 会综合成 数据选择器
    73. // if(~sys_rst_n) begin
    74. // key_out <= 1'b0 ;
    75. // end else begin
    76. // if(end_cnt_20ms) begin
    77. // key_out <= 1'b1 ;
    78. // end else begin
    79. // key_out <= 1'b0 ;
    80. // end
    81. // end
    82. // end
    83. assign key_out = end_cnt_20ms ;
    84. endmodule

     仿真图:忘记截屏了。

    需要用到仿真模型。

    上版验证通过。

  • 相关阅读:
    Pytorch优化器全总结(一)SGD、ASGD、Rprop、Adagrad
    ClickHouse—函数汇总
    SpringBoot--配置Redisson的方法
    MySQL数据库:7、SQL常用查询语句
    ceph报错总结
    R语言绘制动态网络图Network教程WGCNA
    【LeetCode】1838. 最高频元素的频数
    Greenplum数据库故障分析——semop(id=2000421076,num=11) failed: invalid argument
    携创教育:自考本科和成考本科区别在哪?本科自考和成考哪个含金量高点?
    学习笔记——七周成为数据分析师《第一周:数据分析思维》
  • 原文地址:https://blog.csdn.net/Meng_long2022/article/details/133817163