当前位置:   article > 正文

STM32与FPGA Cyclone IV芯片fsmc通信_cyclone4+stm32f407

cyclone4+stm32f407

前言

本文介绍STM32与FPGA通过fsmc通信的实现方法。

一、fsmc介绍

FSMC(Flexible Static Memory Controller,可变静态存储控制器)是STM32系列采用的一种新型的存储器扩展技术。在外部存储器扩展方面具有独特的优势,可根据系统的应用需要,方便地进行不同类型大容量静态存储器的扩展。

该使用方法本质是将FPGA当做SRAM来驱动,支持的存储器类型有SRAM、PSRAM、NOR/ONENAND、ROM、LCD接口(支持8080和6800模式)、NANDFlash和16位的PCCard。

二、平台说明

本次例程使用的处理芯片:STM32F407和Cyclone IV   EP4CE22E144。

三、硬件部分

1.FPGA部分连接方式

2.STM32部分连接方式

STM32引脚连接使用的是复用fsmc功能引脚。

四、软件部分

1.STM32软件部分

STM32 FSMC初始化

  1. /* Includes ------------------------------------------------------------------*/
  2. #include "fsmc.h"
  3. #include "gpio.h"
  4. /* USER CODE BEGIN 0 */
  5. /* USER CODE END 0 */
  6. SRAM_HandleTypeDef hsram1;
  7. /* FSMC initialization function */
  8. void MX_FSMC_Init(void)
  9. {
  10. FSMC_NORSRAM_TimingTypeDef Timing;
  11. HAL_FSMC_MspInit();
  12. /** Perform the SRAM1 memory initialization sequence
  13. */
  14. hsram1.Instance = FSMC_NORSRAM_DEVICE;
  15. hsram1.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
  16. /* hsram1.Init */
  17. hsram1.Init.NSBank = FSMC_NORSRAM_BANK1;
  18. hsram1.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_ENABLE;
  19. hsram1.Init.MemoryType = FSMC_MEMORY_TYPE_PSRAM;
  20. hsram1.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
  21. hsram1.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
  22. hsram1.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
  23. hsram1.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
  24. hsram1.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
  25. hsram1.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;
  26. hsram1.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
  27. hsram1.Init.ExtendedMode = FSMC_EXTENDED_MODE_DISABLE;
  28. hsram1.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_ENABLE;
  29. hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
  30. hsram1.Init.PageSize = FSMC_PAGE_SIZE_NONE;
  31. /* Timing */
  32. Timing.AddressSetupTime = 1;
  33. Timing.AddressHoldTime = 1;
  34. Timing.DataSetupTime = 5;
  35. Timing.BusTurnAroundDuration = 1;
  36. Timing.CLKDivision = 16;
  37. Timing.DataLatency = 17;
  38. Timing.AccessMode = FSMC_ACCESS_MODE_A;
  39. /* ExtTiming */
  40. if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK)
  41. {
  42. _Error_Handler(__FILE__, __LINE__);
  43. }
  44. }
  45. static uint32_t FSMC_Initialized = 0;
  46. static void HAL_FSMC_MspInit(void){
  47. /* USER CODE BEGIN FSMC_MspInit 0 */
  48. /* USER CODE END FSMC_MspInit 0 */
  49. GPIO_InitTypeDef GPIO_InitStruct;
  50. if (FSMC_Initialized) {
  51. return;
  52. }
  53. FSMC_Initialized = 1;
  54. /* Peripheral clock enable */
  55. __HAL_RCC_FSMC_CLK_ENABLE();
  56. /** FSMC GPIO Configuration
  57. PE7 ------> FSMC_DA4
  58. PE8 ------> FSMC_DA5
  59. PE9 ------> FSMC_DA6
  60. PE10 ------> FSMC_DA7
  61. PE11 ------> FSMC_DA8
  62. PE12 ------> FSMC_DA9
  63. PE13 ------> FSMC_DA10
  64. PE14 ------> FSMC_DA11
  65. PE15 ------> FSMC_DA12
  66. PD8 ------> FSMC_DA13
  67. PD9 ------> FSMC_DA14
  68. PD10 ------> FSMC_DA15
  69. PD14 ------> FSMC_DA0
  70. PD15 ------> FSMC_DA1
  71. PD0 ------> FSMC_DA2
  72. PD1 ------> FSMC_DA3
  73. PD3 ------> FSMC_CLK
  74. PD4 ------> FSMC_NOE
  75. PD5 ------> FSMC_NWE
  76. PD6 ------> FSMC_NWAIT
  77. PD7 ------> FSMC_NE1
  78. PB7 ------> FSMC_NL
  79. PE0 ------> FSMC_NBL0
  80. PE1 ------> FSMC_NBL1
  81. */
  82. /* GPIO_InitStruct */
  83. GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
  84. |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
  85. |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1;
  86. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  87. GPIO_InitStruct.Pull = GPIO_NOPULL;
  88. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  89. GPIO_InitStruct.Alternate = GPIO_AF12_FSMC;
  90. HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
  91. /* GPIO_InitStruct */
  92. GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14
  93. |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3
  94. |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
  95. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  96. GPIO_InitStruct.Pull = GPIO_NOPULL;
  97. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  98. GPIO_InitStruct.Alternate = GPIO_AF12_FSMC;
  99. HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  100. /* GPIO_InitStruct */
  101. GPIO_InitStruct.Pin = GPIO_PIN_7;
  102. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  103. GPIO_InitStruct.Pull = GPIO_NOPULL;
  104. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  105. GPIO_InitStruct.Alternate = GPIO_AF12_FSMC;
  106. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  107. /* USER CODE BEGIN FSMC_MspInit 1 */
  108. /* USER CODE END FSMC_MspInit 1 */
  109. }
  110. void HAL_SRAM_MspInit(SRAM_HandleTypeDef* sramHandle){
  111. /* USER CODE BEGIN SRAM_MspInit 0 */
  112. /* USER CODE END SRAM_MspInit 0 */
  113. HAL_FSMC_MspInit();
  114. /* USER CODE BEGIN SRAM_MspInit 1 */
  115. /* USER CODE END SRAM_MspInit 1 */
  116. }
  117. static uint32_t FSMC_DeInitialized = 0;
  118. static void HAL_FSMC_MspDeInit(void){
  119. /* USER CODE BEGIN FSMC_MspDeInit 0 */
  120. /* USER CODE END FSMC_MspDeInit 0 */
  121. if (FSMC_DeInitialized) {
  122. return;
  123. }
  124. FSMC_DeInitialized = 1;
  125. /* Peripheral clock enable */
  126. __HAL_RCC_FSMC_CLK_DISABLE();
  127. /** FSMC GPIO Configuration
  128. PE7 ------> FSMC_DA4
  129. PE8 ------> FSMC_DA5
  130. PE9 ------> FSMC_DA6
  131. PE10 ------> FSMC_DA7
  132. PE11 ------> FSMC_DA8
  133. PE12 ------> FSMC_DA9
  134. PE13 ------> FSMC_DA10
  135. PE14 ------> FSMC_DA11
  136. PE15 ------> FSMC_DA12
  137. PD8 ------> FSMC_DA13
  138. PD9 ------> FSMC_DA14
  139. PD10 ------> FSMC_DA15
  140. PD14 ------> FSMC_DA0
  141. PD15 ------> FSMC_DA1
  142. PD0 ------> FSMC_DA2
  143. PD1 ------> FSMC_DA3
  144. PD4 ------> FSMC_NOE
  145. PD5 ------> FSMC_NWE
  146. PD6 ------> FSMC_NWAIT
  147. PD7 ------> FSMC_NE1
  148. PB7 ------> FSMC_NL
  149. PE0 ------> FSMC_NBL0
  150. PE1 ------> FSMC_NBL1
  151. */
  152. HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
  153. |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
  154. |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1);
  155. HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14
  156. |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4
  157. |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
  158. HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7);
  159. /* USER CODE BEGIN FSMC_MspDeInit 1 */
  160. /* USER CODE END FSMC_MspDeInit 1 */
  161. }
  162. void HAL_SRAM_MspDeInit(SRAM_HandleTypeDef* sramHandle){
  163. /* USER CODE BEGIN SRAM_MspDeInit 0 */
  164. /* USER CODE END SRAM_MspDeInit 0 */
  165. HAL_FSMC_MspDeInit();
  166. /* USER CODE BEGIN SRAM_MspDeInit 1 */
  167. /* USER CODE END SRAM_MspDeInit 1 */
  168. }

STM32通信部分代码:

  1. /* USER CODE END Prototypes */
  2. #define fpga_write(addr_base,data) *((uint16_t *const volatile)(0x60000000 + addr_base)) = (uint16_t)data
  3. #define fpga_read(offset) *((uint16_t *const volatile)(0x60000000 + offset))
  4. //#define fpga_read(offset) *((volatile int32_t* )(0x60000000 + offset))
  5. void fsmc_fpga_write(int addr_base,uint16_t* data,int lenth);
  6. void fsmc_fpga_read(int offset,uint16_t* data,int lenth);

 2.FPGA软件部分

FPGA内部使用avalon总线接口。因此,需要实现fsmc转avalon桥接模块的程序。程序如下:

fsmc_to_avmm

  1. module fsmc_to_avmm(
  2. input csi_clk,
  3. input csi_clk_4x,
  4. input csi_reset_n,
  5. output reg [15 : 0] avm_address,
  6. output reg avm_read_n,
  7. input [15 : 0] avm_readdata,
  8. output reg avm_write_n,
  9. output [15 : 0] avm_writedata,
  10. (* direct_enable = 1 *)
  11. input avm_waitrequest,
  12. output [1 : 0] avm_byteenable,
  13. input coe_nadv,
  14. (* direct_enable = 1 *)
  15. input coe_ne,
  16. input coe_noe,
  17. input coe_nwe,
  18. input [1 : 0] coe_nbl,
  19. output reg coe_nwait,
  20. inout [15 : 0] coe_addr_data_bus
  21. );
  22. reg [1 : 0] meta_nadv;
  23. reg [1 : 0] meta_ne;
  24. reg [1 : 0] meta_noe;
  25. reg [1 : 0] meta_nwe;
  26. reg stb_nadv;
  27. reg stb_ne;
  28. reg stb_noe;
  29. reg stb_nwe;
  30. reg [15 : 0] fsmc_data_out;
  31. reg [15 : 0] addr_latch;
  32. (* direct_enable = 1 *)
  33. reg [15 : 0] write_addr_latch;
  34. reg [15 : 0] data_latch;
  35. reg [1 : 0] byteenable_wr_latch;
  36. reg fifo_wrreq;
  37. reg fifo_rdreq;
  38. wire fifo_almostfull;
  39. wire fifo_empty;
  40. wire fifo_full;
  41. wire [35 : 0] fifo_dout;
  42. wire [7 : 0] fifo_usedw;
  43. (* direct_enable = 1 *)
  44. reg [15 : 0] avm_read_address;
  45. wire [15 : 0] avm_write_address;
  46. reg [15 : 0] avm_readdata_latch;
  47. assign coe_addr_data_bus = (stb_noe) ? 16'bz : fsmc_data_out;
  48. always @ (posedge csi_clk_4x or negedge csi_reset_n)
  49. begin
  50. if (!csi_reset_n) begin
  51. meta_nadv <= 2'b11;
  52. meta_ne <= 2'b11;
  53. meta_noe <= 2'b11;
  54. meta_nwe <= 2'b11;
  55. stb_nadv <= 1;
  56. stb_ne <= 1;
  57. stb_noe <= 1;
  58. stb_nwe <= 1;
  59. end
  60. else begin
  61. meta_nadv <= {meta_nadv[0],coe_nadv};
  62. meta_ne <= {meta_ne[0],coe_ne};
  63. meta_noe <= {meta_noe[0],coe_noe};
  64. meta_nwe <= {meta_nwe[0],coe_nwe};
  65. stb_nadv <= coe_nadv;
  66. stb_ne <= coe_ne;
  67. stb_noe <= coe_noe;
  68. stb_nwe <= coe_nwe;
  69. end
  70. end
  71. always @ (posedge coe_nadv or negedge csi_reset_n)
  72. begin
  73. if (!csi_reset_n) begin
  74. addr_latch <= 16'b0;
  75. end
  76. else begin
  77. if (!coe_ne) begin
  78. addr_latch <= coe_addr_data_bus;
  79. // Should add constraints between addr_latch and csi_clk clock regions
  80. // Recommended to use set_max_delay or set_multicycle_path
  81. end
  82. else begin
  83. addr_latch <= addr_latch;
  84. end
  85. end
  86. end
  87. always @ (posedge coe_nwe or negedge csi_reset_n)
  88. begin
  89. if (!csi_reset_n) begin
  90. data_latch <= 16'b0;
  91. end
  92. else begin
  93. if (!coe_ne) begin
  94. data_latch <= coe_addr_data_bus;
  95. byteenable_wr_latch <= ~coe_nbl;
  96. // Should add constraints between data_latch and csi_clk clock regions
  97. // Recommended to use set_max_delay or set_multicycle_path
  98. end
  99. else begin
  100. data_latch <= data_latch;
  101. byteenable_wr_latch <= byteenable_wr_latch;
  102. end
  103. end
  104. end
  105. reg [2 : 0] fsmc_state;
  106. reg [2 : 0] fsmc_next_state;
  107. localparam FSMC_IDLE = 3'b1;
  108. localparam FSMC_READ = 3'b10;
  109. localparam FSMC_WRITE = 3'b100;
  110. always @ (posedge csi_clk or negedge csi_reset_n)
  111. begin
  112. if (!csi_reset_n) begin
  113. fsmc_state <= FSMC_IDLE;
  114. end
  115. else begin
  116. fsmc_state <= fsmc_next_state;
  117. end
  118. end
  119. always @ (*)
  120. begin
  121. case (fsmc_state)
  122. FSMC_IDLE : begin
  123. casez ({ stb_ne, stb_noe, stb_nwe }) // synthesis full_case
  124. 3'b001 : begin
  125. fsmc_next_state = FSMC_READ;
  126. end
  127. 3'b010 : begin
  128. fsmc_next_state = FSMC_WRITE;
  129. end
  130. 3'b011 : begin
  131. fsmc_next_state = FSMC_IDLE;
  132. end
  133. 3'b1?? : begin
  134. fsmc_next_state = FSMC_IDLE;
  135. end
  136. endcase
  137. end
  138. FSMC_READ : begin
  139. if (stb_noe) begin
  140. fsmc_next_state = FSMC_IDLE;
  141. end
  142. else begin
  143. fsmc_next_state = FSMC_READ;
  144. end
  145. end
  146. FSMC_WRITE : begin
  147. if (stb_nwe) begin
  148. fsmc_next_state = FSMC_IDLE;
  149. end
  150. else begin
  151. fsmc_next_state = FSMC_WRITE;
  152. end
  153. end
  154. default : begin
  155. fsmc_next_state = FSMC_IDLE;
  156. end
  157. endcase
  158. end
  159. always @ (posedge csi_clk or negedge csi_reset_n)
  160. begin
  161. if (!csi_reset_n) begin
  162. avm_read_n <= 1;
  163. avm_readdata_latch <= 0;
  164. fifo_wrreq <= 0;
  165. end
  166. else begin
  167. case (fsmc_state)
  168. FSMC_IDLE : begin
  169. fifo_wrreq <= 0;
  170. casez ({ stb_ne, stb_noe, stb_nwe }) // synthesis full_case
  171. 3'b001 : begin // read
  172. avm_read_n <= 0;
  173. end
  174. 3'b010 : begin // write
  175. end
  176. 3'b011 : begin
  177. avm_read_n <= 1;
  178. end
  179. 3'b1?? : begin // idle
  180. avm_read_n <= 1;
  181. end
  182. endcase
  183. end
  184. FSMC_READ : begin
  185. if (avm_waitrequest) begin
  186. end
  187. else if (avm_read_n == 0) begin
  188. // if (avm_read_n) begin
  189. // fsmc_data_out <= avm_readdata;
  190. // end
  191. // else begin
  192. // fsmc_data_out <= fsmc_data_out;
  193. // end
  194. avm_read_n <= 1;
  195. avm_readdata_latch <= avm_readdata;
  196. end
  197. else begin
  198. end
  199. end
  200. FSMC_WRITE : begin
  201. if (stb_nwe) begin
  202. fifo_wrreq <= 1;
  203. end
  204. else begin
  205. fifo_wrreq <= fifo_wrreq;
  206. end
  207. end
  208. endcase
  209. end
  210. end
  211. always @ (posedge csi_clk or negedge csi_reset_n)
  212. begin
  213. if (!csi_reset_n) begin
  214. avm_read_address <= 0;
  215. write_addr_latch <= 0;
  216. end
  217. else begin
  218. if (!stb_noe) begin
  219. avm_read_address <= addr_latch;
  220. end
  221. else begin
  222. avm_read_address <= avm_read_address;
  223. end
  224. if (!stb_nwe) begin
  225. write_addr_latch <= addr_latch;
  226. // Set a false path or multicycle or max delay from stb_nwe to write_addr_latch
  227. end
  228. else begin
  229. write_addr_latch <= write_addr_latch;
  230. end
  231. end
  232. end
  233. always @ (*)
  234. begin
  235. if (avm_read_n) begin
  236. fsmc_data_out = avm_readdata;//avm_readdata_latch;
  237. end
  238. else begin
  239. fsmc_data_out = avm_readdata_latch;//avm_readdata;
  240. end
  241. end
  242. always @ (*)
  243. begin
  244. if (avm_write_n) begin
  245. avm_address = avm_read_address;
  246. end
  247. else begin
  248. avm_address = avm_write_address;
  249. end
  250. end
  251. always @ (*)
  252. begin
  253. if ((fifo_empty == 0) && (avm_read_n == 1)) begin
  254. avm_write_n = 0;
  255. if (avm_waitrequest == 0) begin
  256. fifo_rdreq = 1;
  257. end
  258. else begin
  259. fifo_rdreq = 0;
  260. end
  261. end
  262. else begin
  263. fifo_rdreq = 0;
  264. avm_write_n = 1;
  265. end
  266. end
  267. /* always @ (*)
  268. begin
  269. (* full_case *)
  270. case(fsmc_state)
  271. FSMC_IDLE : begin
  272. coe_nwait = 1;
  273. end
  274. FSMC_READ : begin
  275. coe_nwait = ~avm_waitrequest;
  276. end
  277. FSMC_WRITE : begin
  278. coe_nwait = ~fifo_almostfull;
  279. end
  280. endcase
  281. end */
  282. always @ (*)
  283. begin
  284. case({ avm_read_n, coe_nwe }) // synthesis full_case
  285. 2'b01 : begin
  286. coe_nwait = ~avm_waitrequest;
  287. end
  288. 2'b10 : begin
  289. coe_nwait = ~fifo_almostfull;
  290. end
  291. 2'b11 : begin
  292. coe_nwait = 0;
  293. end
  294. endcase
  295. end
  296. assign {avm_byteenable, avm_write_address, avm_writedata} = avm_write_n ? {2'b11, 16'b0, 16'b0} : fifo_dout;
  297. scfifo scfifo_component (
  298. .clock (csi_clk),
  299. .data (
  300. {2'b00, // Reserved for checksum
  301. byteenable_wr_latch,
  302. write_addr_latch,
  303. data_latch}),
  304. .rdreq (fifo_rdreq),
  305. .sclr (!csi_reset_n),
  306. .wrreq (fifo_wrreq),
  307. .almost_full (fifo_almostfull),
  308. .empty (fifo_empty),
  309. .full (fifo_full),
  310. .q (fifo_dout),
  311. .usedw (fifo_usedw),
  312. .aclr (),
  313. .almost_empty (),
  314. .eccstatus ());
  315. defparam
  316. scfifo_component.add_ram_output_register = "ON",
  317. scfifo_component.almost_full_value = 250,
  318. scfifo_component.intended_device_family = "Cyclone IV E",
  319. scfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M9K",
  320. scfifo_component.lpm_numwords = 256,
  321. scfifo_component.lpm_showahead = "ON",
  322. scfifo_component.lpm_type = "scfifo",
  323. scfifo_component.lpm_width = 36,
  324. scfifo_component.lpm_widthu = 8,
  325. scfifo_component.overflow_checking = "ON",
  326. scfifo_component.underflow_checking = "ON",
  327. scfifo_component.use_eab = "ON";
  328. endmodule

 fsmc_ctrl

  1. module fmsc_ctrl(
  2. input clk,
  3. input fmsc_WR, //FSMC写信号
  4. input fmsc_RD, //FSMC读信号
  5. input fmsc_CS0, //FSMC片选
  6. input[24:16] fmsc_adress, //FSMC地址总线
  7. input[15:0] fmsc_data, //FSMC数据总线
  8. input fmsc_NADV //FSMC的NADV
  9. );
  10. endmodule

 qsys内部配置如下:

 


总结

STM32部分使用标准fsmc通信功能,FPGA内部使用avalon总线进行通信,因此编写fsmc转avalon总线通信模块。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/384824?site
推荐阅读
相关标签
  

闽ICP备14008679号