• FPGA project : flash_erasure


    SPI是什么:

    SPISerial Peripheral Interface,串行外围设备接口)通讯协议,是Motorola公司提出的一种同步串行接口技术,是一种高速、全双工、同步通信总线,在芯片中只占用四根管脚用来控制及数据传输

           应用:EEPROMFlashRTCADCDSP等。

           优缺点:全双工通信,通讯方式较为简单,相对数据传输速率较没有应答机制确认数据是否接收,在数据可靠性上有一定缺陷(与I2C相比)。

    物理层:

    SCK (Serial Clock):时钟信号线,用于同步通讯数据

    MOSI (Master Output Slave Input):主设备输出/从设备输入引脚

    MISO (Master InputSlave Output):主设备输入/从设备输出引脚

    𝐶𝑆(CS) ̅ (Chip Select):片选信号线,也称为CS_N

    协议层: 

    spi通讯协议有四种模式:模式0和模式3,从设备在sck上升沿采样。

    模式1和模式2在时钟下降沿采样。

    模式0和模式1,在cs_n==1时,sck==0。

    模式2和模式3,在cs_n==1时,sck==1。

    比较常用的就是模式0和模式3。

    flash相关资料:

    芯片手册是必须要看的。

    模块框图:

    状态机:

    时序图:

     代码:

    1. module spi (
    2. input wire sys_clk ,
    3. input wire sys_rst_n ,
    4. input wire key_start ,
    5. output wire mosi ,
    6. output wire miso ,
    7. output reg cs_n ,
    8. output reg sck
    9. );
    10. // parameter
    11. parameter COMD_W = 8'h06 ,
    12. COMD_B = 8'hc7 ;
    13. parameter IDLE = 4'b0001 ,
    14. WREN = 4'b0010 ,
    15. WEL = 4'b0100 ,
    16. BE = 4'b1000 ;
    17. // wire signal degine
    18. wire IDLEtoWREN;
    19. wire WRENtoWEL ;
    20. wire WRENtoBE ;
    21. wire BEtoIDLE ;
    22. // reg signal define
    23. reg [3:0] state_c ;
    24. reg [3:0] state_n ;
    25. reg [3:0] cnt_20ns ;
    26. reg [3:0] cnt_bit ;
    27. reg flag_bit ;
    28. reg f_b_reg ; // flag_bit_reg的缩写
    29. reg [7:0] comd ;
    30. /****************************************************************************/
    31. // 三段式状态机
    32. // 现态与次态描述
    33. // state_c
    34. always @(posedge sys_clk or negedge sys_rst_n) begin
    35. if(~sys_rst_n)
    36. state_c <= IDLE ;
    37. else
    38. state_c <= state_n ;
    39. end
    40. // state_n
    41. always @(*) begin
    42. case (state_c)
    43. IDLE :if(IDLEtoWREN)
    44. state_n <= WREN ;
    45. else
    46. state_n <= IDLE ;
    47. WREN :if(WRENtoWEL)
    48. state_n <= WEL ;
    49. else
    50. state_n <= WREN ;
    51. WEL :if(WRENtoBE)
    52. state_n <= BE ;
    53. else
    54. state_n <= WEL ;
    55. BE :if(BEtoIDLE)
    56. state_n <= IDLE ;
    57. else
    58. state_n <= BE ;
    59. default: state_n <= IDLE ;
    60. endcase
    61. end
    62. // 状态转移描述
    63. assign IDLEtoWREN = ( state_c == IDLE) && ( key_start ) ;
    64. assign WRENtoWEL = ( state_c == WREN) && ( f_b_reg ) ;
    65. assign WRENtoBE = ( state_c == WEL ) && ( cnt_20ns == 6 ) ;
    66. assign BEtoIDLE = ( state_c == BE ) && ( f_b_reg ) ;
    67. // 相关信号描述
    68. // reg [3:0] cnt_20ns ;
    69. always @(posedge sys_clk or negedge sys_rst_n) begin
    70. if(~sys_rst_n)
    71. cnt_20ns <= 4'd0 ;
    72. else
    73. case (state_c)
    74. IDLE : cnt_20ns <= 4'd0 ;
    75. WREN : if(cnt_20ns || f_b_reg)
    76. cnt_20ns <= 4'd0 ;
    77. else
    78. cnt_20ns <= cnt_20ns + 1'b1 ;
    79. WEL : if(cnt_20ns == 6) // 60x20ns==120ns
    80. cnt_20ns <= 4'd0 ;
    81. else
    82. cnt_20ns <= cnt_20ns + 1'b1 ;
    83. BE : if(cnt_20ns || f_b_reg)
    84. cnt_20ns <= 4'd0 ;
    85. else
    86. cnt_20ns <= cnt_20ns + 1'b1 ;
    87. default: cnt_20ns <= 4'd0 ;
    88. endcase
    89. end
    90. // reg [3:0] cnt_bit ;
    91. always @(posedge sys_clk or negedge sys_rst_n) begin
    92. if(~sys_rst_n)
    93. cnt_bit <= 4'd0 ;
    94. else
    95. case (state_c)
    96. IDLE : cnt_bit <= 4'd0 ;
    97. WREN : if(!cnt_20ns && sck && cnt_bit == 7)
    98. cnt_bit <= 4'd0 ;
    99. else if(!cnt_20ns && sck)
    100. cnt_bit <= cnt_bit + 1'b1 ;
    101. WEL : cnt_bit <= 4'd0 ;
    102. BE : if(!cnt_20ns && sck && cnt_bit == 7)
    103. cnt_bit <= 4'd0 ;
    104. else if(!cnt_20ns && sck)
    105. cnt_bit <= cnt_bit + 1'b1 ;
    106. default: cnt_bit <= 4'd0 ;
    107. endcase
    108. end
    109. // reg flag_bit ;
    110. always @(posedge sys_clk or negedge sys_rst_n) begin
    111. if(~sys_rst_n)
    112. flag_bit <= 1'b0 ;
    113. else
    114. case (state_c)
    115. IDLE : flag_bit <= 1'b0 ;
    116. WREN : if(cnt_bit == 7 && sck && !cnt_20ns)
    117. flag_bit <= 1'b1 ;
    118. else
    119. flag_bit <= flag_bit ;
    120. WEL : flag_bit <= 1'b0 ;
    121. BE : if(cnt_bit == 7 && sck && !cnt_20ns)
    122. flag_bit <= 1'b1 ;
    123. else
    124. flag_bit <= flag_bit ;
    125. default: flag_bit <= 1'b0 ;
    126. endcase
    127. end
    128. // reg f_b_reg ;
    129. always @(posedge sys_clk or negedge sys_rst_n) begin
    130. if(~sys_rst_n) begin
    131. f_b_reg <= 1'b0 ;
    132. end else begin
    133. f_b_reg <= flag_bit ;
    134. end
    135. end
    136. // reg [7:0] comd ;
    137. always @(posedge sys_clk or negedge sys_rst_n) begin
    138. if(~sys_rst_n)
    139. comd <= 8'd0 ;
    140. else
    141. case (state_c)
    142. IDLE : comd <= 8'd0 ;
    143. WREN : if(cnt_20ns && sck)
    144. comd <= (COMD_W << cnt_bit) ;
    145. else if(!cnt_bit)
    146. comd <= COMD_W ;
    147. else
    148. comd <= comd ;
    149. WEL : comd <= 8'd0 ;
    150. BE : if(cnt_20ns && sck)
    151. comd <= (COMD_B << cnt_bit) ;
    152. else if(!cnt_bit)
    153. comd <= COMD_B ;
    154. else
    155. comd <= comd ;
    156. default : comd <= 8'd0 ;
    157. endcase
    158. end
    159. // output signal
    160. // wire mosi ,
    161. assign mosi = comd[7] ;
    162. // wire miso ,
    163. assign miso = 1'bz ;
    164. // reg cs_n ,
    165. always @(posedge sys_clk or negedge sys_rst_n) begin
    166. if(~sys_rst_n) begin
    167. cs_n <= 1'b1 ;
    168. end else begin
    169. case (state_c)
    170. IDLE : if(key_start)
    171. cs_n <= 1'b0 ;
    172. else
    173. cs_n <= 1'b1 ;
    174. WREN : if(f_b_reg)
    175. cs_n <= 1'b1 ;
    176. else
    177. cs_n <= cs_n ;
    178. WEL : if(cnt_20ns == 6)
    179. cs_n <= 1'b0 ;
    180. else
    181. cs_n <= cs_n ;
    182. BE : if(f_b_reg)
    183. cs_n <= 1'b1 ;
    184. else
    185. cs_n <= cs_n ;
    186. default: cs_n <= 1'b1 ;
    187. endcase
    188. end
    189. end
    190. // reg sck
    191. always @(posedge sys_clk or negedge sys_rst_n) begin
    192. if(~sys_rst_n)
    193. sck <= 1'b0 ;
    194. else
    195. case (state_c)
    196. IDLE : sck <= 1'b0 ;
    197. WREN : if(cnt_20ns)
    198. sck <= ~sck ;
    199. else
    200. sck <= sck ;
    201. WEL : sck <= 1'b0 ;
    202. BE : if(cnt_20ns)
    203. sck <= ~sck ;
    204. else
    205. sck <= sck ;
    206. default: sck <= 1'b0 ;
    207. endcase
    208. end
    209. 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
    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. `timescale 1ns/1ns
    2. module test_top();
    3. reg sys_clk ;
    4. reg sys_rst_n ;
    5. reg key_in ;
    6. wire cs_n ;
    7. wire sck ;
    8. wire mosi ;
    9. wire miso ;
    10. top top_inst(
    11. .sys_clk ( sys_clk ) ,
    12. .sys_rst_n ( sys_rst_n ) ,
    13. .key_in ( key_in ) ,
    14. .cs_n ( cs_n ) ,
    15. .sck ( sck ) ,
    16. .mosi ( mosi ) ,
    17. .miso ( miso )
    18. );
    19. parameter CYCLE = 20 ;
    20. defparam top_inst.key_filter_inst.MAX_CNT_20MS = 20'd100 ;
    21. initial begin
    22. sys_clk = 1'b1 ;
    23. sys_rst_n <= 1'b0 ;
    24. key_in <= 1'b1 ;
    25. #(CYCLE) ;
    26. sys_rst_n <= 1'b1 ;
    27. #(CYCLE * 30) ;
    28. key_in <= 1'b0 ;
    29. #(CYCLE * 130) ;
    30. key_in <= 1'b1 ;
    31. #(CYCLE * 100) ;
    32. $stop;
    33. end
    34. always #(CYCLE/2) sys_clk = ~sys_clk ;
    35. endmodule

     仿真波形:

     上板验证:

    先往板子上固化一个流水灯程序,也就是把生成的.jic文件,写进flash。

    重启开发板,流水灯正常工作,说明程序写进了flash。

    然后把全擦除程序(.sof),写进开发板。

    重启开发板,流水灯效果消失。

    说明上板成功。

  • 相关阅读:
    抓包海康摄像头gb28181,抓不到任何sip的包
    加密货币熊市导致收入骤降,穆迪将Coinbase降级
    葡萄酒数据集
    企业电子招标采购系统项目说明+开发类型+解决方案+功能描述+二次开发+spring cloud
    【“在路上”疫情信息检测】——项目基础框架搭建
    关于设置图标
    网络安全——SQL报错注入
    深度学习应用篇-元学习[13]:元学习概念、学习期、工作原理、模型分类等
    信息化与信息系统3
    celery笔记八之数据库操作定时任务
  • 原文地址:https://blog.csdn.net/Meng_long2022/article/details/133758120