FMC与FPGA双口ram通讯

硬件环境:ARM+FPGA通过FMC互联,STM32F767和 EP4CE15F23I7

FMC设置,STM的系统时钟HCLK为216MHz

 1 /* FMC initialization function */
 2 void MX_FMC_Init(void)
 3 {
 4   FMC_NORSRAM_TimingTypeDef Timing;
 5 
 6   /** Perform the NOR1 memory initialization sequence
 7   */
 8   hnor1.Instance = FMC_NORSRAM_DEVICE;
 9   hnor1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
10   /* hnor1.Init */
11   hnor1.Init.NSBank = FMC_NORSRAM_BANK1;
12   hnor1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
13   hnor1.Init.MemoryType = FMC_MEMORY_TYPE_NOR;
14   hnor1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
15   hnor1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
16   hnor1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
17   hnor1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
18   hnor1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
19   hnor1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
20   hnor1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
21   hnor1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
22   hnor1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
23   hnor1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
24   hnor1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
25   hnor1.Init.PageSize = FMC_PAGE_SIZE_NONE;
26   /* Timing */
27   Timing.AddressSetupTime = 5;   
28   Timing.AddressHoldTime = 1;    
29   Timing.DataSetupTime = 4; 
30   Timing.BusTurnAroundDuration = 0;
31   Timing.CLKDivision = 0;
32   Timing.DataLatency = 0;
33   Timing.AccessMode = FMC_ACCESS_MODE_A;
34   /* ExtTiming */
35 
36   if (HAL_NOR_Init(&hnor1, &Timing, NULL) != HAL_OK)
37   {
38     _Error_Handler(__FILE__, __LINE__);
39   }
40 }

verilog核心代码,其中双口ram的a口与FPGA内部模块相连,b口与ARMFMC端口相连,clk时钟为100MHz

 1 reg wr_clk1,wr_clk2;.
 2 wire rd = (cs0 | rdn);
 3 wire wr = (cs0 | wrn);
 4 wire clk_b = (!wr_clk2 | !rd);
 5 
 6 ram u1(
 7     .data_a(data_a),
 8     .address_a(address_a),
 9     .wren_a(wren_a),
10     .rden_a(rden_a),
11     .clock_a(clk_50m),
12     .q_a(dataout_a),
13     
14     .data_b(db),
15     .address_b(ab),
16     .wren_b(!wr),
17     .rden_b(!rd),
18     .clock_b(clk_b),
19     .q_b(dataout_b)
20 );
21 
22 always@(posedge clk_100m or negedge rst_n)
23     if(!rst_n)
24         begin
25             wr_clk1 <= 1'd1;
26             wr_clk2 <= 1'd1;
27         end
28     else 
29         {wr_clk2,wr_clk1} <= {wr_clk1,wr};
30         
31 assign db = !rd ? dataout_b : 16'hzzzz;

在SignalTap中调试发现有时写入丢失(写入后读出不正常),时序上具体体现为

上图中wr信号丢失,造成部分写入失败,wr由ARM输出,与FPGA时钟异步,这里是时钟匹配问题,导致信号丢失,查看STM32F7XX手册关于FMC时序:

图中可以看到,  rd与ADDSET时间有关,wr与DATAST-1时间有关,结合前面FMC程序中

Timing.DataSetupTime = 4;

那么wr理论时间是3*HCLK = 3/216MHZ  ≈14ns, FPGA时钟周期10ns,理论上wr信号不会丢失。猜想可能是异步信号,同时信号边沿存在斜率(有条件可以用示波器捕捉验证),可能存在信号丢失现象,这里修改FMC时间配置参数。

1 /* Timing */
2   Timing.AddressSetupTime = 9;   
3   Timing.AddressHoldTime = 1;    
4   Timing.DataSetupTime = 8;      
5   Timing.BusTurnAroundDuration = 0;
6   Timing.CLKDivision = 0;
7   Timing.DataLatency = 0;
8   Timing.AccessMode = FMC_ACCESS_MODE_A;

修改后发现以上问题得到解决,调试时序如下:

猜你喜欢

转载自www.cnblogs.com/qqff/p/11098912.html