GD32通过EXMC读写FPGA
- 硬件
- GD32代码设计
- FPGA代码设计
1.## 硬件设计
采用的芯片分别是GD32F303VET6和LFE5U-45F-6BG256I
硬件设计原因前期开发阶段只使用其中A20-A22三根地址线,可对应8个寄存器地址
2.## GD32代码设计
#define ARM_FPGA_REG0 *((volatile unsigned short*)((uint32_t)0x60000000))
#define ARM_FPGA_REG1 *((volatile unsigned short*)((uint32_t)0x60200000))
#define ARM_FPGA_REG2 *((volatile unsigned short*)((uint32_t)0x60400000))
#define ARM_FPGA_REG3 *((volatile unsigned short*)((uint32_t)0x60600000))
#define ARM_FPGA_REG4 *((volatile unsigned short*)((uint32_t)0x60800000))
#define ARM_FPGA_REG5 *((volatile unsigned short*)((uint32_t)0x60a00000))
#define ARM_FPGA_REG6 *((volatile unsigned short*)((uint32_t)0x60c00000))
#define ARM_FPGA_REG7 *((volatile unsigned short*)((uint32_t)0x60e00000))
void exmc_sram_init(void)
{
exmc_norsram_parameter_struct sdram_init_struct;
exmc_norsram_timing_parameter_struct read_write_timing;
/* enable EXMC clock*/
rcu_periph_clock_enable(RCU_EXMC);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_GPIOE);
rcu_periph_clock_enable(RCU_GPIOF);
rcu_periph_clock_enable(RCU_GPIOG);
/* EXMC GPIO */
/* D0(PB0) D1(PB1) D2(PB2) D3(PB10) D4(PB11) D5(PB12) D6(PB13) D7(PB14) D8(PB15) D9(PB3) D10(PB4) D11(PB5) D12(PB6) D13(PB7) D14(PB8) D15(PB9)*/
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2| GPIO_PIN_3| GPIO_PIN_4| GPIO_PIN_5
| GPIO_PIN_6| GPIO_PIN_7| GPIO_PIN_8| GPIO_PIN_9| GPIO_PIN_10| GPIO_PIN_11| GPIO_PIN_12| GPIO_PIN_13| GPIO_PIN_14 | GPIO_PIN_15);
/* A1(PE2) A2(PE3)A3(PE4)A4(PE5)A5(PE6)A6(PE7)A7(PE8)A8(PE9)A9(PE10)A10(PE11)A11(PE0)A12(PE1) */
gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2| GPIO_PIN_3| GPIO_PIN_4| GPIO_PIN_5
| GPIO_PIN_6| GPIO_PIN_7| GPIO_PIN_8| GPIO_PIN_9| GPIO_PIN_10| GPIO_PIN_11);
/* NCE1(PD7) pin configuration */
gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
// /* NWAIT(PC7) pin configuration */
// gpio_init(GPIOC, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
/* NOE(PD4) and NWE(PD5) pins configuration*/
gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4 | GPIO_PIN_5);
/* configure read/write timing */
//use SARM
read_write_timing.asyn_access_mode = EXMC_ACCESS_MODE_A;//ģʽA Òì²½·ÃÎÊSRAM
read_write_timing.asyn_address_setuptime = 8;
read_write_timing.asyn_data_setuptime = 80;
//not use SARM
read_write_timing.asyn_address_holdtime = 0;
read_write_timing.syn_data_latency = 0;
read_write_timing.bus_latency = 0;
read_write_timing.syn_clk_division = 0;
/* configure the structure with default values */
sdram_init_struct.norsram_region = EXMC_BANK0_NORSRAM_REGION0; //NE0
sdram_init_struct.address_data_mux = DISABLE; //
sdram_init_struct.memory_type = EXMC_MEMORY_TYPE_SRAM; //SRAM
sdram_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B; //16bit
sdram_init_struct.burst_mode = DISABLE;
sdram_init_struct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
sdram_init_struct.wrap_burst_mode = DISABLE;
sdram_init_struct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
sdram_init_struct.memory_write = ENABLE;
sdram_init_struct.nwait_signal = DISABLE;
sdram_init_struct.extended_mode = DISABLE;
sdram_init_struct.asyn_wait = DISABLE; /*!< enable or disable the asynchronous wait function */
sdram_init_struct.write_mode = EXMC_ASYN_WRITE; /*!< asynchronous write mode */
sdram_init_struct.read_write_timing = &read_write_timing;
sdram_init_struct.write_timing = &read_write_timing;
exmc_norsram_init(&sdram_init_struct);
exmc_norsram_enable(EXMC_BANK0_NORSRAM_REGION0);
}
int main(void)
{
uint32_t i = 0;
uint16_t j = 0;
systick_config();
gd_eval_led_init(LED2);
exmc_sram_init();
while(1)
{
*((volatile unsigned short *)0x60000000) = 0xC11C;
sys_clk_freq1=*((volatile unsigned short *)0x60000000);
*((volatile unsigned short *)0x60200000) = 0xC22C;
sys_clk_freq2=*((volatile unsigned short *)0x60200000);
*((volatile unsigned short *)0x60400000) = 0xC33C;
sys_clk_freq3=*((volatile unsigned short *)0x60400000);
*((volatile unsigned short *)0x60600000) = 0xC44C;
sys_clk_freq4=*((volatile unsigned short *)0x60600000);
*((volatile unsigned short *)0x60800000) = 0xC55C;
sys_clk_freq5=*((volatile unsigned short *)0x60800000);
*((volatile unsigned short *)0x60a00200) = 0xC66C;
sys_clk_freq6=*((volatile unsigned short *)0x60a00200);
*((volatile unsigned short *)0x60c00000) = 0xC77C;
sys_clk_freq7=*((volatile unsigned short *)0x60c00000);
*((volatile unsigned short *)0x60e00000) = 0xC88C;
sys_clk_freq8=*((volatile unsigned short *)0x60e00000);
}
}
2.## FPGA代码设计
/* STM32与FPGA之间的FSMC通讯 */
module STM32_FPGA(
input FPGA_CLK,
input sys_rst_n,
input [2:0] exmc_A,
inout [15:0] exmc_D,
input FPGA_CS0,//FPGA片选段
input RD,//ARM从FPGA读数据
input WR,//ARM写数据到FPGA
output clk
//output led,
//output led1
);
wire clk;
pll2 pll2(
.CLKI( FPGA_CLK ),//8M
.CLKOP (clk ) //72M
);
/*reg [24:0] cnt = 0;
always @(posedge FPGA_CLK or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt <= 25'd0;
else
cnt <= cnt + 1'b1;
assign led = cnt[24];*/
//FPGA内部8个数据存放的寄存器
reg [15:0] ARM_FPGA_REG0;
reg [15:0] ARM_FPGA_REG1;
reg [15:0] ARM_FPGA_REG2;
reg [15:0] ARM_FPGA_REG3;
reg [15:0] ARM_FPGA_REG4;
reg [15:0] ARM_FPGA_REG5;
reg [15:0] ARM_FPGA_REG6;
reg [15:0] ARM_FPGA_REG7;
wire rd_en;
wire wr_en;
assign wr_en = ~FPGA_CS0 && ~WR;//写使能
assign rd_en = ~FPGA_CS0 && ~RD;//读使能
reg [15:0] data_reg;
//根据地址线,ARM从FPGA中读取对应寄存器数据放在寄存器data_reg中
/*always@(posedge FPGA_CLK or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
data_reg <= 16'd0;
else if(rd_en)
begin*/
// always@(posedge clk)//!
always@(*)
begin
if(rd_en)
begin
case(exmc_A[2:0])
3'd0 : data_reg <= ARM_FPGA_REG0;
3'd1 : data_reg <= ARM_FPGA_REG1;
3'd2 : data_reg <= ARM_FPGA_REG2;
3'd3 : data_reg <= ARM_FPGA_REG3;
3'd4 : data_reg <= ARM_FPGA_REG4;
3'd5 : data_reg <= ARM_FPGA_REG5;
3'd6 : data_reg <= ARM_FPGA_REG6;
3'd7 : data_reg <= ARM_FPGA_REG7;
default: ;
endcase
end
end
/* WR上升沿STM32的数据写入FPGA,即sampling point */
reg WR_tmp1;
reg WR_tmp2;
//always@(*)
always @(posedge clk)
//always @(posedge FPGA_CLK)
begin
WR_tmp1 <= WR;
WR_tmp2 <= WR_tmp1;
end
wire WR_RISING = ~WR_tmp2 && WR_tmp1;//与clk同步
always @(*)
begin
if(WR_RISING)
begin
case(exmc_A[2:0])
3'd0 : ARM_FPGA_REG0 <= exmc_D;
3'd1 : ARM_FPGA_REG1 <= exmc_D;
3'd2 : ARM_FPGA_REG2 <= exmc_D;
3'd3 : ARM_FPGA_REG3 <= exmc_D;
3'd4 : ARM_FPGA_REG4 <= exmc_D;
3'd5 : ARM_FPGA_REG5 <= exmc_D;
3'd6 : ARM_FPGA_REG6 <= exmc_D;
3'd7 : ARM_FPGA_REG7 <= exmc_D;
default: ;
endcase
end
end
assign exmc_D = rd_en ? data_reg : 16'hzzzz;
endmodule