基於通過STM32的FSMC總線讀取FPGA的實現


硬件環境是ICORE FPGA與ARM的雙核心開發板

STM32配置的FSMC的代碼(寄存器操作模式):

static int 

initialize(void)
{
GPIOD_R->CRH.W = 0xbbbbbbbb;
GPIOD_R->CRL.W = 0xbbbbbbbb;

GPIOE_R->CRH.W = 0xbbbbbbbb;
GPIOE_R->CRL.W = 0xbbbbbbbb;

FSMC_Bank1_R->BCR1 &= ~(1 << 1 | 1 << 2 | 1 << 3);

FSMC_Bank1_R->BCR1 |= 1 << 14; //EXTMOD

FSMC_Bank1_R->BTR1 = 0x300;

FSMC_Bank1E_R->BWTR1 = 0X300;

return 0;
}

icore 利用STM32的FSMC的地址總線AB23 AB22 跟CS 通過138譯碼器 擴展出4路片選信號,CS0,CS1,CS2,CS3

CS0為FPGA的片選信號 4路片選的宏定義如下所示:

#define CS0_BASE (0x60000000 + (0 << 23))

#define CS1_BASE (0x60000000 + (1 << 23))
#define CS2_BASE (0x60000000 + (2 << 23))
#define CS3_BASE (0x60000000 + (3 << 23))

在icore的fsmc讀取fpga的例程中利用STM32的FSMC的地址總線AB18、AB17、AB16進行對FPGA內部的存儲空間地址選擇,

這樣只能定義8個16位的空間

#define fpga_write(offset, data) *((volatile unsigned short int*)(CS0_BASE + (offset << 17))) = data

#define fpga_read(offset) *((volatile unsigned short int*)(CS0_BASE + (offset << 17)))    

以下對這部分代碼進行修改

#define fpga_write_addr         *((volatile unsigned short int*)(CS0_BASE))      
#define fpga_write_read         *((volatile unsigned short int*)(CS0_BASE)+ (1 << 16))

這樣就利用AB18、AB17、AB16組合的8個空間中的2個 但可以擴展出更多的空間

fpga_write_addr   用於向fpga寫入所要訪問空間的1地址

fpga_write_read   用於對已定義地址空間數據的讀寫

調用下面代碼就可實現讀寫

static int
fpga_w(uint16_t addr,uint16_t data)         往FPGA中寫數據函數如 fpga_w(1,230); 往空間1 中寫入230
{
fpga_write_addr = addr;
fpga_write_read = data;
return 1;
}
static int
fpga_r(uint16_t addr)            往FPGA中讀取數據函數如   data = fpga_r(1); 讀取空間1 中的數據存入data
{
uint16_t data=0;
fpga_write_addr = addr;
data = fpga_write_read ;
return data;
}

FPGA實現代碼

fsmc.v模塊的代碼如下 

module fsmc(
input[2:0] ab,
inout[15:0] data,

input clk_f,
input wrn,
input rdn,
input resetn,
input fpga_cs0,

output sing
);

reg [15:0] mem_d[7:0];      //定義數據空間 大小自己可以設定
reg [15:0] addr;                 //數據空間的地址
reg [15:0] indata;
reg [24:0] cnt;

reg rd;
reg wr;


always @(*)
begin
  rd <= ~fpga_cs0 && ~rdn;
  wr <= ~fpga_cs0 && ~wrn;
end

//---------------------------------------------------

always @(posedge clk_f)
cnt <= cnt + 1'b1;
assign sing = wr|rd;//|cnt[24];

initial begin
  mem_d[0] = 16'd120;
  mem_d[1] = 16'd121;
  mem_d[2] = 16'd122;
  mem_d[3] = 16'd123;
  mem_d[4] = 16'd124;
  mem_d[5] = 16'd125;
  mem_d[6] = 16'd126;
  mem_d[7] = 16'd127;
end

//---------------------------------------------------
//write data, 
always @(posedge wr)// or negedge resetn)
begin
  if(wr)//(!resetn)
  begin
    case (ab)
      3'b000:addr <= data;            //地址暫存
      3'b001:mem_d[addr[3:0]] <= data;   //往預設地址的空間中寫入數據
    default: ;
    endcase
  end
end

//red data 
always @(posedge rd)//(rd)// or negedge resetn
begin
  if(rd)//(!resetn) indata <= 16'h0000;
  begin
    case (ab)
      3'b000:;
      3'b001: indata <= mem_d[addr[3:0]];    //讀取數據
    default:;
    endcase
  end
end

assign data = rd ? indata:16'hzzzz;

endmodule

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM