赞
踩
1.很多情况下,fpga的内部ip ram的存储量较小,所以需要外挂容量大的芯片。内部的芯片ram称为静态ram,其读写简单,速率中等,缺点就是存储空间较小。spartan—6芯片的最小单元为9k;充电刷新保持数据的额sdram称为动态ram,其容量大,缺点就是高功耗,管脚多,操作时许复杂,占用面积大。无论是静态还是动态ram都是一种易失性器件。
2.当前比较常用的是ddr3,有关ddr3的介绍https://baike.baidu.com/item/DDR3/9505741?fr=aladdin;fpga的spartan6家族中,有一个IP称为MCB(存储控制模块),本文主要就是对控制模块的读写控制,然后通过读写模块对ddr3的数据进行写入与读取。
3.模块的数据流与读写时序如下:
整个模块的基本数据流就是图所示,本文设计一个display的控制模块,对整个模块进行一个数据验证。而ddr3_rd_ctrl的模块中,申请了一个fifo_2048的fifoIP核,来对ddr3存储的数据进行读取与显示。而frame_start的信号等同于显示器的行列驱动同步,pixel_vaild_o相当于有效显示区域。这个模块需要2个不同频率的时钟,对ddr3的读模块需要125M的时钟,显示模块为50M时钟。
这个ddr3的数据读取的模块控制时序,需要说明的是读模块要先发出读命令然后才可以读取数据,而写模块要写入数据才可以发出写命令。MCB的fifo的使能信号需要严格控制。
3.ddr3的读写主要控制模块程序
- module wr_ddr3_ctrl(
-
- input wire sclk,
- input wire rst,
- input wire P2_DATA_EMPTY,
- input wire c3_calib_done,
-
- output wire[31:0] P2_DATA, // P2_DATA
- output wire P2_DATA_WR_EN, //P2_DATA_WR_EN
- output wire[3:0] P2_data_mask,
-
- output wire P2_CMD_WR_EN, //P2_CMD_WR_EN
- output wire[2:0] P2_CMD_INSTR, //P2_CMD_INSTR
- output wire[5:0] P2_CMD_BL, //P2_CMD_BL
- output wire[29:0] P2_CMD_ADDR //P2_CMD_ADDR
-
- );
-
- reg wr_data_en;
- reg [5:0] data_cnt=0;
- reg [31:0] wr_data=0;
- reg [5:0] burst_cnt=0;
- reg done_dely;
- wire wr_start_flag;
- reg wr_cmd_en;
- reg wr_cycle=0;
- reg [29:0] wr_addr=0;
-
-
- assign P2_CMD_BL=6'd63;
- assign P2_CMD_INSTR=3'b000;
- assign P2_data_mask=4'b0000;
- assign P2_CMD_ADDR=wr_addr;
- assign P2_CMD_WR_EN=wr_cmd_en;
- assign P2_DATA_WR_EN=wr_data_en;
- assign P2_DATA=wr_data;
-
- always@(posedge sclk)
- if(rst==1)
- done_dely<=0;
- else done_dely<=c3_calib_done;
- assign wr_start_flag=~(done_dely)&(c3_calib_done);
- always@(posedge sclk ) //
- if(rst==1)
- wr_data_en<=1'b0;
- else if(wr_start_flag==1||(wr_cycle==1&&P2_DATA_EMPTY==1))
- wr_data_en<=1'b1;
- else if(data_cnt=='d63)
- wr_data_en<=1'b0;
- always@(posedge sclk ) //
- if(rst==1)
- data_cnt<='d0;
- else if(wr_data_en==1)
- data_cnt<=data_cnt+1'b1;
- else data_cnt<='d0;
-
-
- always@(posedge sclk) //
- if(rst==1)
- wr_data<='d0;
- else if(wr_data_en==1&&data_cnt==63&&burst_cnt==63)
- wr_data<='d0;
- else if(wr_data_en==1)
- wr_data<=wr_data+1;
-
- always@(posedge sclk) //
- if(rst==1)
- burst_cnt<='d0;
- else if(wr_data_en==1&&data_cnt==63)
- burst_cnt<=burst_cnt+1'b1;
-
- always@(posedge sclk) //
- if(rst==1)
- wr_cmd_en<=1'b0;
- else if(wr_data_en==1&&data_cnt==63)
- wr_cmd_en<=1'b1;
- else wr_cmd_en<=1'b0;
-
- always@(posedge sclk) //
- if(rst==1)
- wr_cycle<='d0;
- else if(wr_data_en==1&&data_cnt==63&&burst_cnt==63)
- wr_cycle<='d0;
- else if(wr_start_flag==1)
- wr_cycle<=1;
-
- always@(posedge sclk) //
- if(rst==1)
- wr_addr<='d0;
- else if(wr_cmd_en==1)
- wr_addr<=wr_addr+256;
-
- endmodule

- module ddr3_rd(
-
- input wire sclk,
- input wire wr_sclk,
- input wire rst,
- input wire c3_calib_done,
- input wire frame_start,
- input wire pixel_vaild_o,
- input wire p3_rd_full,
- input wire [31:0] p3_rd_data,
-
- output reg p3_cmd_en,
- output wire [2:0] p3_cmd_inst,
- output wire [5:0] p3_cmd_bl,
- output reg [29:0] p3_cmd_byte_addr,
- output reg p3_rd_fifo_en,
- output wire [31:0] pixel_data
- );
-
- reg ddr3_ready;
- wire [10:0] wr_f_cnt;
- reg rd_ddr3_cycle;
- reg [5:0] data_cnt;
- reg user_fifo_wr_en;
- wire [10:0] r_f_cnt;
- reg fifo_enable_read;
- wire user_fifo_rd_en;
-
- assign p3_cmd_bl=63;
- assign p3_cmd_inst=001;
-
- always@(posedge wr_sclk)
- if(rst==1)
- ddr3_ready<=0;
- else ddr3_ready<=c3_calib_done;
-
- always@(posedge wr_sclk)
- if(rst==1)
- rd_ddr3_cycle<=0;
- else if(data_cnt==63)
- rd_ddr3_cycle<=0;
- else if(ddr3_ready==1&&wr_f_cnt<1024)
- rd_ddr3_cycle<=1;
-
-
- always@(posedge wr_sclk)
- if(rst==1)
- p3_cmd_en<=0;
- else if(ddr3_ready==1&&wr_f_cnt<1024&&rd_ddr3_cycle==0)
- p3_cmd_en<=1;
- else p3_cmd_en<=0;
-
-
- always@(posedge wr_sclk)
- if(rst==1)
- p3_rd_fifo_en<=1'b0;
- else if(data_cnt==63)
- p3_rd_fifo_en<=1'b0;
- else if(rd_ddr3_cycle==1&&p3_rd_full==1)
- p3_rd_fifo_en<=1'b1;
-
-
- always@(posedge wr_sclk)
- if(rst==1)
- p3_cmd_byte_addr<=30'd0;
- else if(p3_cmd_en==1&&p3_cmd_byte_addr==30'h3f00)
- p3_cmd_byte_addr<=30'd0;
- else if(p3_cmd_en==1)
- p3_cmd_byte_addr<=p3_cmd_byte_addr+256;
-
-
-
- always@(posedge wr_sclk)
- if(rst==1)
- data_cnt<=6'd0;
- else if(data_cnt==63)
- data_cnt<=6'd0;
- else if(rd_ddr3_cycle==1&&p3_rd_fifo_en==1)
- data_cnt<=data_cnt+1'b1;
- always@(posedge wr_sclk)
- if(rst==1)
- user_fifo_wr_en<=1'b0;
- else if(rd_ddr3_cycle==1&&p3_rd_full==1)
- user_fifo_wr_en<=1'b1;
- else if(data_cnt==63)
- user_fifo_wr_en<=1'b0;
-
- always@(posedge sclk)
- if(rst==1)
- fifo_enable_read<=1'b0;
- else if(r_f_cnt>1024&&frame_start==1)
- fifo_enable_read<=1'b1;
-
- assign user_fifo_rd_en=fifo_enable_read&pixel_vaild_o;
-
- fifo_wr2048_32 fifo_wr2048_32_inst (
- .wr_clk(wr_sclk), // input wr_clk *125M
- .rd_clk(sclk), // input rd_clk *50M
- .din(p3_rd_data), // input [31 : 0] din
- .wr_en(user_fifo_wr_en), // input wr_en
- .rd_en(user_fifo_rd_en), // input rd_en
- .dout(pixel_data), // output [31 : 0] dout
- .full(full), // output full
- .empty(empty), // output empty
- .rd_data_count(r_f_cnt), // output [10 : 0] rd_data_count
- .wr_data_count(wr_f_cnt) // output [10 : 0] wr_data_count
- );
-
- endmodule

4.模块时序仿真需要很多时间,仿真才是关键。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。