DDR2(6):8通道的DDR2控制器

       前文说道,我毕业设计的一部分是实现8目摄像头的传图显示,并基于此做一些核心图像处理。一晃时间就过去了多年,当初在实验室同窗共砚,召唤师峡谷切磋拳剑,情景宛在目前。临风远念,想诸位师兄同窗,岁至中年,然风采笑貌,当如昔日也…

  图像处理部分是导师的课题核心,不方便公开,但 8 通道的 DDR2 控制器是参考网络资料后自行设计的代码,这里分享出来,希望后来者遇到类似课题,能够有所帮助。

  总体框图如下所示:

image

 

  以下是源码,其中 DDR2_8port 是控制器的顶层文件,当时做了两个版本,两个版本的内部都调用了 DDR2_burst 模块和 FIFO 模块。

1、DDR2_8port v1

(1) inst

inst
//==========================================================================
//==                        DDR2_8port
//==========================================================================
DDR2_8port  u_DDR2_8port
(
    //时钟和复位 ------------------------------------
    .pll_ref_clk            (clk_100m               ),  //DDR2输入时钟
    .global_reset_n         (sys_rst_n              ),  //全局复位信号
    //DDR2端口 -------------------------------------- 
    .mem_odt                (mem_odt                ),  //DDR2片上终结信号
    .mem_cs_n               (mem_cs_n               ),  //DDR2片选信号
    .mem_cke                (mem_cke                ),  //DDR2时钟使能信号
    .mem_addr               (mem_addr               ),  //DDR2地址总线
    .mem_ba                 (mem_ba                 ),  //DDR2BANK信号
    .mem_ras_n              (mem_ras_n              ),  //DDR2行地址选择信号
    .mem_cas_n              (mem_cas_n              ),  //DDR2列地址选择信号
    .mem_we_n               (mem_we_n               ),  //DDR2写使能信号
    .mem_dm                 (mem_dm                 ),  //DDR2数据掩膜信号
    .mem_clk                (mem_clk                ),  //DDR2时钟信号
    .mem_clk_n              (mem_clk_n              ),  //DDR2时钟反相信号
    .mem_dq                 (mem_dq                 ),  //DDR2数据总线
    .mem_dqs                (mem_dqs                ),  //DDR2数据源同步信号
    //DDR2控制 --------------------------------------     
    .DDR2_rst_n             (                       ),  //DDR2 IP核同步复位
    .pingpang_vld           (1'b1                   ),  //乒乓操作
    .min_addr               (0                      ),  //最小地址
    .max_addr               (320*360                ),  //最大地址
    .burst_len              (80                     ),  //突发长度(行/4)
    //通道0 -----------------------------------------
    .ch0_en                 (1'b1                   ),  //通道0 使能
    .ch0_addr               (3'h0                   ),  //通道0 地址
    .ch0_wr_clk             (ch0_clk                ),  //通道0 写侧时钟
    .ch0_wr_data            (ch0_data               ),  //通道0 写侧数据
    .ch0_wr_vld             (ch0_vld                ),  //通道0 写侧有效
    .ch0_wr_vsync           (ch0_vsync              ),  //通道0 写侧同步
    .ch0_rd_clk             (clk_VGA                ),  //通道0 读侧时钟
    .ch0_rd_data            (ch0_VGA_din            ),  //通道0 读侧数据
    .ch0_rd_req             (ch0_VGA_req            ),  //通道0 读侧请求
    .ch0_rd_vsync           (VGA_vsync              ),  //通道0 读侧同步
    //通道1 -----------------------------------------
    .ch1_en                 (1'b1                   ),  //通道1 使能
    .ch1_addr               (3'h1                   ),  //通道1 地址
    .ch1_wr_clk             (ch1_clk                ),  //通道1 写侧时钟
    .ch1_wr_data            (ch1_data               ),  //通道1 写侧数据
    .ch1_wr_vld             (ch1_vld                ),  //通道1 写侧有效
    .ch1_wr_vsync           (ch1_vsync              ),  //通道1 写侧同步
    .ch1_rd_clk             (clk_VGA                ),  //通道1 读侧时钟
    .ch1_rd_data            (ch1_VGA_din            ),  //通道1 读侧数据
    .ch1_rd_req             (ch1_VGA_req            ),  //通道1 读侧请求
    .ch1_rd_vsync           (VGA_vsync              ),  //通道1 读侧同步
    //通道2 -----------------------------------------
    .ch2_en                 (1'b1                   ),  //通道2 使能
    .ch2_addr               (3'h2                   ),  //通道2 地址
    .ch2_wr_clk             (ch2_clk                ),  //通道2 写侧时钟
    .ch2_wr_data            (ch2_data               ),  //通道2 写侧数据
    .ch2_wr_vld             (ch2_vld                ),  //通道2 写侧有效
    .ch2_wr_vsync           (ch2_vsync              ),  //通道2 写侧同步
    .ch2_rd_clk             (clk_VGA                ),  //通道2 读侧时钟
    .ch2_rd_data            (ch2_VGA_din            ),  //通道2 读侧数据
    .ch2_rd_req             (ch2_VGA_req            ),  //通道2 读侧请求
    .ch2_rd_vsync           (VGA_vsync              ),  //通道2 读侧同步
    //通道3 -----------------------------------------
    .ch3_en                 (1'b1                   ),  //通道3 使能
    .ch3_addr               (3'h3                   ),  //通道3 地址
    .ch3_wr_clk             (ch3_clk                ),  //通道3 写侧时钟
    .ch3_wr_data            (ch3_data               ),  //通道3 写侧数据
    .ch3_wr_vld             (ch3_vld                ),  //通道3 写侧有效
    .ch3_wr_vsync           (ch3_vsync              ),  //通道3 写侧同步
    .ch3_rd_clk             (clk_VGA                ),  //通道3 读侧时钟
    .ch3_rd_data            (ch3_VGA_din            ),  //通道3 读侧数据
    .ch3_rd_req             (ch3_VGA_req            ),  //通道3 读侧请求
    .ch3_rd_vsync           (VGA_vsync              ),  //通道3 读侧同步
    //通道4 -----------------------------------------
    .ch4_en                 (1'b1                   ),  //通道4 使能
    .ch4_addr               (3'h4                   ),  //通道4 地址
    .ch4_wr_clk             (ch4_clk                ),  //通道4 写侧时钟
    .ch4_wr_data            (ch4_data               ),  //通道4 写侧数据
    .ch4_wr_vld             (ch4_vld                ),  //通道4 写侧有效
    .ch4_wr_vsync           (ch4_vsync              ),  //通道4 写侧同步
    .ch4_rd_clk             (clk_VGA                ),  //通道4 读侧时钟
    .ch4_rd_data            (ch4_VGA_din            ),  //通道4 读侧数据
    .ch4_rd_req             (ch4_VGA_req            ),  //通道4 读侧请求
    .ch4_rd_vsync           (VGA_vsync              ),  //通道4 读侧同步
    //通道5 -----------------------------------------
    .ch5_en                 (1'b1                   ),  //通道5 使能
    .ch5_addr               (3'h5                   ),  //通道5 地址
    .ch5_wr_clk             (ch5_clk                ),  //通道5 写侧时钟
    .ch5_wr_data            (ch5_data               ),  //通道5 写侧数据
    .ch5_wr_vld             (ch5_vld                ),  //通道5 写侧有效
    .ch5_wr_vsync           (ch5_vsync              ),  //通道5 写侧同步
    .ch5_rd_clk             (clk_VGA                ),  //通道5 读侧时钟
    .ch5_rd_data            (ch5_VGA_din            ),  //通道5 读侧数据
    .ch5_rd_req             (ch5_VGA_req            ),  //通道5 读侧请求
    .ch5_rd_vsync           (VGA_vsync              ),  //通道5 读侧同步
    //通道6 -----------------------------------------
    .ch6_en                 (1'b1                   ),  //通道6 使能
    .ch6_addr               (3'h6                   ),  //通道6 地址
    .ch6_wr_clk             (ch6_clk                ),  //通道6 写侧时钟
    .ch6_wr_data            (ch6_data               ),  //通道6 写侧数据
    .ch6_wr_vld             (ch6_vld                ),  //通道6 写侧有效
    .ch6_wr_vsync           (ch6_vsync              ),  //通道6 写侧同步
    .ch6_rd_clk             (clk_VGA                ),  //通道6 读侧时钟
    .ch6_rd_data            (ch6_VGA_din            ),  //通道6 读侧数据
    .ch6_rd_req             (ch6_VGA_req            ),  //通道6 读侧请求
    .ch6_rd_vsync           (VGA_vsync              ),  //通道6 读侧同步
    //通道7 -----------------------------------------
    .ch7_en                 (1'b1                   ),  //通道7 使能
    .ch7_addr               (3'h7                   ),  //通道7 地址
    .ch7_wr_clk             (ch7_clk                ),  //通道7 写侧时钟
    .ch7_wr_data            (ch7_data               ),  //通道7 写侧数据
    .ch7_wr_vld             (ch7_vld                ),  //通道7 写侧有效
    .ch7_wr_vsync           (ch7_vsync              ),  //通道7 写侧同步
    .ch7_rd_clk             (clk_VGA                ),  //通道7 读侧时钟
    .ch7_rd_data            (ch7_VGA_din            ),  //通道7 读侧数据
    .ch7_rd_req             (ch7_VGA_req            ),  //通道7 读侧请求
    .ch7_rd_vsync           (VGA_vsync              )   //通道7 读侧同步
);

(2) DDR2_8port

DDR2_8port
//**************************************************************************
// *** 名称 : DDR2_8port.v
// *** 作者 : xianyu_FPGA
// *** 博客 : https://www.cnblogs.com/xianyufpga/
// *** 日期 : 2020年6月
// *** 描述 : 多通道视频读写突发的控制模块,每个通道都可以选择是否使用
//**************************************************************************

module DDR2_8port
//============================< 参数 >======================================
#(
parameter MEM_DM_W              = 4                     ,   //DDR2 dm位宽
parameter MEM_DQS_W             = 4                     ,   //DDR2 dqs位宽
parameter MEM_BANK_W            = 3                     ,   //DDR2 bank位宽
parameter MEM_ADDR_W            = 13                    ,   //DDR2 地址位宽
parameter MEM_DQ_W              = 32                    ,   //DDR2 数据位宽,一片16两片32
//-------------------------------------------------------
parameter LOCAL_SIZE_W          = 3                     ,   //DDR2 IP核local_size位宽
parameter LOCAL_DATA_W          = 64                    ,   //DDR2 IP核数据位宽
parameter LOCAL_ADDR_W          = 25                        //DDR2 IP核地址位宽
)
//============================< 端口 >======================================
(
//时钟和复位 --------------------------------------------
input                           pll_ref_clk             ,   //DDR2输入时钟
input                           global_reset_n          ,   //全局复位信号
//DDR2端口 ----------------------------------------------
output                          mem_odt                 ,   //DDR2片上终结信号
output                          mem_cs_n                ,   //DDR2片选信号
output                          mem_cke                 ,   //DDR2时钟使能信号
output  [MEM_ADDR_W   -1:0]     mem_addr                ,   //DDR2地址总线
output  [MEM_BANK_W   -1:0]     mem_ba                  ,   //DDR2BANK信号
output                          mem_ras_n               ,   //DDR2行地址选择信号
output                          mem_cas_n               ,   //DDR2列地址选择信号
output                          mem_we_n                ,   //DDR2写使能信号
output  [MEM_DM_W     -1:0]     mem_dm                  ,   //DDR2数据掩膜信号
inout                           mem_clk                 ,   //DDR2时钟信号
inout                           mem_clk_n               ,   //DDR2时钟反相信号
inout   [MEM_DQ_W     -1:0]     mem_dq                  ,   //DDR2数据总线
inout   [MEM_DQS_W    -1:0]     mem_dqs                 ,   //DDR2数据源同步信号
//DDR3控制 ----------------------------------------------
output                          DDR2_rst_n              ,   //DDR2 同步复位
input                           pingpang_vld            ,   //乒乓操作
input   [LOCAL_ADDR_W -3:0]     min_addr                ,   //起始地址,3位选通1位乒乓再扩大4倍:-4+2
input   [LOCAL_ADDR_W -3:0]     max_addr                ,   //结束地址,3位选通1位乒乓再扩大4倍:-4+2
input   [LOCAL_ADDR_W -3:0]     burst_len               ,   //突发长度
//通道0 -------------------------------------------------
input                           ch0_en                  ,   //通道0 使能
input   [ 2:0]                  ch0_addr                ,   //通道0 地址
input                           ch0_wr_clk              ,   //通道0 写侧时钟
input   [15:0]                  ch0_wr_data             ,   //通道0 写侧数据
input                           ch0_wr_vld              ,   //通道0 写侧有效
input                           ch0_wr_vsync            ,   //通道0 写侧同步
input                           ch0_rd_clk              ,   //通道0 读侧时钟
output  [15:0]                  ch0_rd_data             ,   //通道0 读侧数据
input                           ch0_rd_req              ,   //通道0 读侧请求
input                           ch0_rd_vsync            ,   //通道0 读侧同步
//通道1 -------------------------------------------------
input                           ch1_en                  ,   //通道1 使能
input   [ 2:0]                  ch1_addr                ,   //通道1 地址
input                           ch1_wr_clk              ,   //通道1 写侧时钟
input   [15:0]                  ch1_wr_data             ,   //通道1 写侧数据
input                           ch1_wr_vld              ,   //通道1 写侧有效
input                           ch1_wr_vsync            ,   //通道1 写侧同步
input                           ch1_rd_clk              ,   //通道1 读侧时钟
output  [15:0]                  ch1_rd_data             ,   //通道1 读侧数据
input                           ch1_rd_req              ,   //通道1 读侧请求
input                           ch1_rd_vsync            ,   //通道1 读侧同步
//通道2 -------------------------------------------------
input                           ch2_en                  ,   //通道2 使能
input   [ 2:0]                  ch2_addr                ,   //通道2 地址
input                           ch2_wr_clk              ,   //通道2 写侧时钟
input   [15:0]                  ch2_wr_data             ,   //通道2 写侧数据
input                           ch2_wr_vld              ,   //通道2 写侧有效
input                           ch2_wr_vsync            ,   //通道2 写侧同步
input                           ch2_rd_clk              ,   //通道2 读侧时钟
output  [15:0]                  ch2_rd_data             ,   //通道2 读侧数据
input                           ch2_rd_req              ,   //通道2 读侧请求
input                           ch2_rd_vsync            ,   //通道2 读侧同步
//通道3 -------------------------------------------------
input                           ch3_en                  ,   //通道3 使能
input   [ 2:0]                  ch3_addr                ,   //通道3 地址
input                           ch3_wr_clk              ,   //通道3 写侧 时钟
input   [15:0]                  ch3_wr_data             ,   //通道3 写侧 数据
input                           ch3_wr_vld              ,   //通道3 写侧 有效
input                           ch3_wr_vsync            ,   //通道3 写侧 同步
input                           ch3_rd_clk              ,   //通道3 读侧 时钟
output  [15:0]                  ch3_rd_data             ,   //通道3 读侧 数据
input                           ch3_rd_req              ,   //通道3 读侧 请求
input                           ch3_rd_vsync            ,   //通道3 读侧 同步
//通道4 -------------------------------------------------
input                           ch4_en                  ,   //通道4 使能
input   [ 2:0]                  ch4_addr                ,   //通道4 地址
input                           ch4_wr_clk              ,   //通道4 写侧时钟
input   [15:0]                  ch4_wr_data             ,   //通道4 写侧数据
input                           ch4_wr_vld              ,   //通道4 写侧有效
input                           ch4_wr_vsync            ,   //通道4 写侧同步
input                           ch4_rd_clk              ,   //通道4 读侧时钟
output  [15:0]                  ch4_rd_data             ,   //通道4 读侧数据
input                           ch4_rd_req              ,   //通道4 读侧请求
input                           ch4_rd_vsync            ,   //通道4 读侧同步
//通道5 -------------------------------------------------
input                           ch5_en                  ,   //通道5 使能
input   [ 2:0]                  ch5_addr                ,   //通道5 地址
input                           ch5_wr_clk              ,   //通道5 写侧时钟
input   [15:0]                  ch5_wr_data             ,   //通道5 写侧数据
input                           ch5_wr_vld              ,   //通道5 写侧有效
input                           ch5_wr_vsync            ,   //通道5 写侧同步
input                           ch5_rd_clk              ,   //通道5 读侧时钟
output  [15:0]                  ch5_rd_data             ,   //通道5 读侧数据
input                           ch5_rd_req              ,   //通道5 读侧请求
input                           ch5_rd_vsync            ,   //通道5 读侧同步
//通道6 -------------------------------------------------
input                           ch6_en                  ,   //通道6 使能
input   [ 2:0]                  ch6_addr                ,   //通道6 地址
input                           ch6_wr_clk              ,   //通道6 写侧时钟
input   [15:0]                  ch6_wr_data             ,   //通道6 写侧数据
input                           ch6_wr_vld              ,   //通道6 写侧有效
input                           ch6_wr_vsync            ,   //通道6 写侧同步
input                           ch6_rd_clk              ,   //通道6 读侧时钟
output  [15:0]                  ch6_rd_data             ,   //通道6 读侧数据
input                           ch6_rd_req              ,   //通道6 读侧请求
input                           ch6_rd_vsync            ,   //通道6 读侧 同步
//通道0 -------------------------------------------------
input                           ch7_en                  ,   //通道7 使能
input   [ 2:0]                  ch7_addr                ,   //通道7 地址
input                           ch7_wr_clk              ,   //通道7 写侧时钟
input   [15:0]                  ch7_wr_data             ,   //通道7 写侧数据
input                           ch7_wr_vld              ,   //通道7 写侧有效
input                           ch7_wr_vsync            ,   //通道7 写侧同步
input                           ch7_rd_clk              ,   //通道7 读侧时钟
output  [15:0]                  ch7_rd_data             ,   //通道7 读侧数据
input                           ch7_rd_req              ,   //通道7 读侧请求
input                           ch7_rd_vsync                //通道7 读侧同步
);
//============================< 信号 >======================================
wire                            phy_clk                 ;   //DDR2工作时钟
wire    [LOCAL_DATA_W -1:0]     burst_rd_data           ;   //读突发数据
wire    [LOCAL_DATA_W -1:0]     burst_wr_data           ;   //写突发数据
wire                            burst_rd_ack            ;   //读突发应答信号
wire                            burst_wr_ack            ;   //写突发应答信号
wire                            burst_rd_done           ;   //突发读完成信号
wire                            burst_wr_done           ;   //突发写完成信号
reg                             burst_wr_req            ;   //突发写请求
reg                             burst_rd_req            ;   //突发读请求
//FIFO --------------------------------------------------
wire    [LOCAL_DATA_W -1:0]     ch0_wrFIFO_q            ;   //通道0读数据
wire    [LOCAL_DATA_W -1:0]     ch1_wrFIFO_q            ;   //通道1读数据
wire    [LOCAL_DATA_W -1:0]     ch2_wrFIFO_q            ;   //通道2读数据
wire    [LOCAL_DATA_W -1:0]     ch3_wrFIFO_q            ;   //通道3读数据
wire    [LOCAL_DATA_W -1:0]     ch4_wrFIFO_q            ;   //通道4读数据
wire    [LOCAL_DATA_W -1:0]     ch5_wrFIFO_q            ;   //通道5读数据
wire    [LOCAL_DATA_W -1:0]     ch6_wrFIFO_q            ;   //通道6读数据
wire    [LOCAL_DATA_W -1:0]     ch7_wrFIFO_q            ;   //通道7读数据
wire    [ 7:0]                  ch0_wrFIFO_rdusedw      ;   //通道0写FIFO剩余数据个数
wire    [ 7:0]                  ch1_wrFIFO_rdusedw      ;   //通道1写FIFO剩余数据个数
wire    [ 7:0]                  ch2_wrFIFO_rdusedw      ;   //通道2写FIFO剩余数据个数
wire    [ 7:0]                  ch3_wrFIFO_rdusedw      ;   //通道3写FIFO剩余数据个数
wire    [ 7:0]                  ch4_wrFIFO_rdusedw      ;   //通道4写FIFO剩余数据个数
wire    [ 7:0]                  ch5_wrFIFO_rdusedw      ;   //通道5写FIFO剩余数据个数
wire    [ 7:0]                  ch6_wrFIFO_rdusedw      ;   //通道6写FIFO剩余数据个数
wire    [ 7:0]                  ch7_wrFIFO_rdusedw      ;   //通道7写FIFO剩余数据个数
wire    [ 7:0]                  ch0_rdFIFO_wrusedw      ;   //通道0读FIFO剩余数据个数
wire    [ 7:0]                  ch1_rdFIFO_wrusedw      ;   //通道1读FIFO剩余数据个数
wire    [ 7:0]                  ch2_rdFIFO_wrusedw      ;   //通道2读FIFO剩余数据个数
wire    [ 7:0]                  ch3_rdFIFO_wrusedw      ;   //通道3读FIFO剩余数据个数
wire    [ 7:0]                  ch4_rdFIFO_wrusedw      ;   //通道4读FIFO剩余数据个数
wire    [ 7:0]                  ch5_rdFIFO_wrusedw      ;   //通道5读FIFO剩余数据个数
wire    [ 7:0]                  ch6_rdFIFO_wrusedw      ;   //通道6读FIFO剩余数据个数
wire    [ 7:0]                  ch7_rdFIFO_wrusedw      ;   //通道7读FIFO剩余数据个数
//FIFO异步清0 -------------------------------------------
reg                             ch0_wr_vsync_r          ;   //通道0 写的场信号打一拍
reg                             ch1_wr_vsync_r          ;   //通道1 写的场信号打一拍
reg                             ch2_wr_vsync_r          ;   //通道2 写的场信号打一拍
reg                             ch3_wr_vsync_r          ;   //通道3 写的场信号打一拍
reg                             ch4_wr_vsync_r          ;   //通道4 写的场信号打一拍
reg                             ch5_wr_vsync_r          ;   //通道5 写的场信号打一拍
reg                             ch6_wr_vsync_r          ;   //通道6 写的场信号打一拍
reg                             ch7_wr_vsync_r          ;   //通道7 写的场信号打一拍
reg                             ch0_rd_vsync_r          ;   //通道0 写的场信号打一拍
reg                             ch1_rd_vsync_r          ;   //通道1 写的场信号打一拍
reg                             ch2_rd_vsync_r          ;   //通道2 写的场信号打一拍
reg                             ch3_rd_vsync_r          ;   //通道3 写的场信号打一拍
reg                             ch4_rd_vsync_r          ;   //通道4 写的场信号打一拍
reg                             ch5_rd_vsync_r          ;   //通道5 写的场信号打一拍
reg                             ch6_rd_vsync_r          ;   //通道6 写的场信号打一拍
reg                             ch7_rd_vsync_r          ;   //通道7 写的场信号打一拍
wire                            ch0_wr_rst              ;   //通道0 写的场复位信号
wire                            ch1_wr_rst              ;   //通道1 写的场复位信号
wire                            ch2_wr_rst              ;   //通道2 写的场复位信号
wire                            ch3_wr_rst              ;   //通道3 写的场复位信号
wire                            ch4_wr_rst              ;   //通道4 写的场复位信号
wire                            ch5_wr_rst              ;   //通道5 写的场复位信号
wire                            ch6_wr_rst              ;   //通道6 写的场复位信号
wire                            ch7_wr_rst              ;   //通道7 写的场复位信号
wire                            ch0_rd_rst              ;   //通道0 写的场复位信号
wire                            ch1_rd_rst              ;   //通道1 写的场复位信号
wire                            ch2_rd_rst              ;   //通道2 写的场复位信号
wire                            ch3_rd_rst              ;   //通道3 写的场复位信号
wire                            ch4_rd_rst              ;   //通道4 写的场复位信号
wire                            ch5_rd_rst              ;   //通道5 写的场复位信号
wire                            ch6_rd_rst              ;   //通道6 写的场复位信号
wire                            ch7_rd_rst              ;   //通道7 写的场复位信号
//-------------------------------------------------------
reg                             ch0_wr_addr_msb         ;   //通道0乒乓操作写分区
reg                             ch0_rd_addr_msb         ;   //通道0乒乓操作读分区
reg                             ch1_wr_addr_msb         ;   //通道1乒乓操作写分区
reg                             ch1_rd_addr_msb         ;   //通道1乒乓操作读分区
reg                             ch2_wr_addr_msb         ;   //通道2乒乓操作写分区
reg                             ch2_rd_addr_msb         ;   //通道2乒乓操作读分区
reg                             ch3_wr_addr_msb         ;   //通道3乒乓操作写分区
reg                             ch3_rd_addr_msb         ;   //通道3乒乓操作读分区
reg                             ch4_wr_addr_msb         ;   //通道4乒乓操作写分区
reg                             ch4_rd_addr_msb         ;   //通道4乒乓操作读分区
reg                             ch5_wr_addr_msb         ;   //通道5乒乓操作写分区
reg                             ch5_rd_addr_msb         ;   //通道5乒乓操作读分区
reg                             ch6_wr_addr_msb         ;   //通道6乒乓操作写分区
reg                             ch6_rd_addr_msb         ;   //通道6乒乓操作读分区
reg                             ch7_wr_addr_msb         ;   //通道7乒乓操作写分区
reg                             ch7_rd_addr_msb         ;   //通道7乒乓操作读分区
//-------------------------------------------------------
reg     [LOCAL_ADDR_W  -3:2]    ch0_wr_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch1_wr_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch2_wr_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch3_wr_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch4_wr_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch5_wr_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch6_wr_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch7_wr_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch0_rd_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch1_rd_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch2_rd_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch3_rd_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch4_rd_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch5_rd_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch6_rd_addr             ;   //地址除以4
reg     [LOCAL_ADDR_W  -3:2]    ch7_rd_addr             ;   //地址除以4
//-------------------------------------------------------
wire    [LOCAL_ADDR_W  -1:0]    burst_wr_addr           ;   //写突发地址
wire    [LOCAL_ADDR_W  -1:0]    burst_rd_addr           ;   //读突发地址
reg     [ 2:0]                  wr_ch                   ;   //写通道
reg     [ 2:0]                  rd_ch                   ;   //读通道
reg     [ 5:0]                  state                   ;   //状态机
//============================< 参数 >======================================
localparam IDLE                 = 6'b000001             ;   //空闲
localparam ARBIT                = 6'b000010             ;   //仲裁
localparam WR                   = 6'b000100             ;   //写
localparam WR_DONE              = 6'b001000             ;   //写完成
localparam RD                   = 6'b010000             ;   //读
localparam RD_DONE              = 6'b100000             ;   //读完成
//==========================================================================
//==    DDR2突发读写模块,实现一段长度的突发读写
//==========================================================================
DDR2_burst u_DDR2_burst
(
    //DDR2 IP核接口 -------------------------------------
    .pll_ref_clk                (pll_ref_clk            ),  //DDR2 参考时钟 
    .global_reset_n             (global_reset_n         ),  //DDR2 全局复位
    .phy_clk                    (phy_clk                ),  //DDR2 工作时钟
    .DDR2_rst_n                 (DDR2_rst_n             ),  //DDR2 同步复位
    //突发读写接口 --------------------------------------
    .burst_rd_req               (burst_rd_req           ),  //突发读请求
    .burst_wr_req               (burst_wr_req           ),  //突发写请求
    .burst_rd_len               (burst_len              ),  //突发读长度
    .burst_wr_len               (burst_len              ),  //突发写长度
    .burst_rd_addr              (burst_rd_addr          ),  //突发读地址
    .burst_wr_addr              (burst_wr_addr          ),  //突发写地址
    .burst_rd_data              (burst_rd_data          ),  //突发读数据
    .burst_wr_data              (burst_wr_data          ),  //突发写数据
    .burst_rd_ack               (burst_rd_ack           ),  //突发读应答,连接FIFO
    .burst_wr_ack               (burst_wr_ack           ),  //突发写应答,连接FIFO
    .burst_rd_done              (burst_rd_done          ),  //突发读完成信号
    .burst_wr_done              (burst_wr_done          ),  //突发写完成信号   
    //DDR2 芯片接口 --------------------------------------
    .mem_odt                    (mem_odt                ),  //DDR2片上终结信号
    .mem_cs_n                   (mem_cs_n               ),  //DDR2片选信号
    .mem_cke                    (mem_cke                ),  //DDR2时钟使能信号
    .mem_addr                   (mem_addr               ),  //DDR2地址总线  
    .mem_ba                     (mem_ba                 ),  //DDR2bank信号
    .mem_ras_n                  (mem_ras_n              ),  //DDR2行地址选择信号
    .mem_cas_n                  (mem_cas_n              ),  //DDR2列地址选择信号
    .mem_we_n                   (mem_we_n               ),  //DDR2写使能信号
    .mem_dm                     (mem_dm                 ),  //DDR2数据掩膜信号
    .mem_clk                    (mem_clk                ),  //DDR2时钟信号
    .mem_clk_n                  (mem_clk_n              ),  //DDR2时钟反相信号
    .mem_dq                     (mem_dq                 ),  //DDR2数据总线
    .mem_dqs                    (mem_dqs                )   //DDR2数据源同步信号
);
//==========================================================================
//==    FIFO的异步复位
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch0_wr_vsync_r <= 1'b0;
        ch1_wr_vsync_r <= 1'b0;
        ch2_wr_vsync_r <= 1'b0;
        ch3_wr_vsync_r <= 1'b0;
        ch4_wr_vsync_r <= 1'b0;
        ch5_wr_vsync_r <= 1'b0;
        ch6_wr_vsync_r <= 1'b0;
        ch7_wr_vsync_r <= 1'b0;
        
        ch0_rd_vsync_r <= 1'b0;
        ch1_rd_vsync_r <= 1'b0;
        ch2_rd_vsync_r <= 1'b0;
        ch3_rd_vsync_r <= 1'b0;
        ch4_rd_vsync_r <= 1'b0;
        ch5_rd_vsync_r <= 1'b0;
        ch6_rd_vsync_r <= 1'b0;
        ch7_rd_vsync_r <= 1'b0;
    end
    else begin
        ch0_wr_vsync_r <= ch0_wr_vsync;
        ch1_wr_vsync_r <= ch1_wr_vsync;
        ch2_wr_vsync_r <= ch2_wr_vsync;
        ch3_wr_vsync_r <= ch3_wr_vsync;
        ch4_wr_vsync_r <= ch4_wr_vsync;
        ch5_wr_vsync_r <= ch5_wr_vsync;
        ch6_wr_vsync_r <= ch6_wr_vsync;
        ch7_wr_vsync_r <= ch7_wr_vsync;
        
        ch0_rd_vsync_r <= ch0_rd_vsync;
        ch1_rd_vsync_r <= ch1_rd_vsync;
        ch2_rd_vsync_r <= ch2_rd_vsync;
        ch3_rd_vsync_r <= ch3_rd_vsync;
        ch4_rd_vsync_r <= ch4_rd_vsync;
        ch5_rd_vsync_r <= ch5_rd_vsync;
        ch6_rd_vsync_r <= ch6_rd_vsync;
        ch7_rd_vsync_r <= ch7_rd_vsync;
    end
end

assign ch0_wr_rst = 0;//ch0_wr_vsync_r && !ch0_wr_vsync;
assign ch1_wr_rst = 0;//ch1_wr_vsync_r && !ch1_wr_vsync;
assign ch2_wr_rst = 0;//ch2_wr_vsync_r && !ch2_wr_vsync;
assign ch3_wr_rst = 0;//ch3_wr_vsync_r && !ch3_wr_vsync;
assign ch4_wr_rst = 0;//ch4_wr_vsync_r && !ch4_wr_vsync;
assign ch5_wr_rst = 0;//ch5_wr_vsync_r && !ch5_wr_vsync;
assign ch6_wr_rst = 0;//ch6_wr_vsync_r && !ch6_wr_vsync;
assign ch7_wr_rst = 0;//ch7_wr_vsync_r && !ch7_wr_vsync;

assign ch0_rd_rst = !ch0_rd_vsync_r && ch0_rd_vsync;
assign ch1_rd_rst = !ch1_rd_vsync_r && ch1_rd_vsync;
assign ch2_rd_rst = !ch2_rd_vsync_r && ch2_rd_vsync;
assign ch3_rd_rst = !ch3_rd_vsync_r && ch3_rd_vsync;
assign ch4_rd_rst = !ch4_rd_vsync_r && ch4_rd_vsync;
assign ch5_rd_rst = !ch5_rd_vsync_r && ch5_rd_vsync;
assign ch6_rd_rst = !ch6_rd_vsync_r && ch6_rd_vsync;
assign ch7_rd_rst = !ch7_rd_vsync_r && ch7_rd_vsync;
//==========================================================================
//==    根据FIFO的状态,选择读写操作通道
//==========================================================================
//写通道
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        wr_ch <= 3'h0;
    end
    else if(state == ARBIT && ch0_en && ch0_wrFIFO_rdusedw >= burst_len) begin
        wr_ch <= 3'h0;
    end
    else if(state == ARBIT && ch1_en && ch1_wrFIFO_rdusedw >= burst_len) begin
        wr_ch <= 3'h1;
    end
    else if(state == ARBIT && ch2_en && ch2_wrFIFO_rdusedw >= burst_len) begin
        wr_ch <= 3'h2;
    end
    else if(state == ARBIT && ch3_en && ch3_wrFIFO_rdusedw >= burst_len) begin
        wr_ch <= 3'h3;
    end
    else if(state == ARBIT && ch4_en && ch4_wrFIFO_rdusedw >= burst_len) begin
        wr_ch <= 3'h4;
    end
    else if(state == ARBIT && ch5_en && ch5_wrFIFO_rdusedw >= burst_len) begin
        wr_ch <= 3'h5;
    end
    else if(state == ARBIT && ch6_en && ch6_wrFIFO_rdusedw >= burst_len) begin
        wr_ch <= 3'h6;
    end
    else if(state == ARBIT && ch7_en && ch7_wrFIFO_rdusedw >= burst_len) begin
        wr_ch <= 3'h7;
    end
end

//读通道
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        rd_ch <= 3'h0;
    end
    else if(state == ARBIT && ch0_en && ch0_rdFIFO_wrusedw < burst_len) begin
        rd_ch <= 3'h0;
    end
    else if(state == ARBIT && ch1_en && ch1_rdFIFO_wrusedw < burst_len) begin
        rd_ch <= 3'h1;
    end
    else if(state == ARBIT && ch2_en && ch2_rdFIFO_wrusedw < burst_len) begin
        rd_ch <= 3'h2;
    end
    else if(state == ARBIT && ch3_en && ch3_rdFIFO_wrusedw < burst_len) begin
        rd_ch <= 3'h3;
    end
    else if(state == ARBIT && ch4_en && ch4_rdFIFO_wrusedw < burst_len) begin
        rd_ch <= 3'h4;
    end
    else if(state == ARBIT && ch5_en && ch5_rdFIFO_wrusedw < burst_len) begin
        rd_ch <= 3'h5;
    end
    else if(state == ARBIT && ch6_en && ch6_rdFIFO_wrusedw < burst_len) begin
        rd_ch <= 3'h6;
    end
    else if(state == ARBIT && ch7_en && ch7_rdFIFO_wrusedw < burst_len) begin
        rd_ch <= 3'h7;
    end
end
//==========================================================================
//==    FIFO
//==========================================================================
//写FIFO通道0
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch0
(
    .wrclk          (ch0_wr_clk                     ),
    .wrreq          (ch0_wr_vld                     ),
    .data           (ch0_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wr_ack && wr_ch==3'h0    ),
    .q              (ch0_wrFIFO_q                   ),
    .rdusedw        (ch0_wrFIFO_rdusedw             ),
    .aclr           (!DDR2_rst_n || ch0_wr_rst      )
);

//写FIFO通道1
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch1
(
    .wrclk          (ch1_wr_clk                     ),
    .wrreq          (ch1_wr_vld                     ),
    .data           (ch1_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wr_ack && wr_ch==3'h1    ),
    .q              (ch1_wrFIFO_q                   ),
    .rdusedw        (ch1_wrFIFO_rdusedw             ),
    .aclr           (!DDR2_rst_n || ch1_wr_rst      )
);

//写FIFO通道2
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch2
(
    .wrclk          (ch2_wr_clk                     ),
    .wrreq          (ch2_wr_vld                     ),
    .data           (ch2_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wr_ack && wr_ch==3'h2    ),
    .q              (ch2_wrFIFO_q                   ),
    .rdusedw        (ch2_wrFIFO_rdusedw             ),
    .aclr           (!DDR2_rst_n || ch2_wr_rst      )
);

//写FIFO通道3
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch3
(
    .wrclk          (ch3_wr_clk                     ),
    .wrreq          (ch3_wr_vld                     ),
    .data           (ch3_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wr_ack && wr_ch==3'h3    ),
    .q              (ch3_wrFIFO_q                   ),
    .rdusedw        (ch3_wrFIFO_rdusedw             ),
    .aclr           (!DDR2_rst_n || ch3_wr_rst      )
);

//写FIFO通道4
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch4
(
    .wrclk          (ch4_wr_clk                     ),
    .wrreq          (ch4_wr_vld                     ),
    .data           (ch4_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wr_ack && wr_ch==3'h4    ),
    .q              (ch4_wrFIFO_q                   ),
    .rdusedw        (ch4_wrFIFO_rdusedw             ),
    .aclr           (!DDR2_rst_n || ch4_wr_rst      )
);

//写FIFO通道5
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch5
(
    .wrclk          (ch5_wr_clk                     ),
    .wrreq          (ch5_wr_vld                     ),
    .data           (ch5_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wr_ack && wr_ch==3'h5    ),
    .q              (ch5_wrFIFO_q                   ),
    .rdusedw        (ch5_wrFIFO_rdusedw             ),
    .aclr           (!DDR2_rst_n || ch5_wr_rst      )
);

//写FIFO通道6
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch6
(
    .wrclk          (ch6_wr_clk                     ),
    .wrreq          (ch6_wr_vld                     ),
    .data           (ch6_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wr_ack && wr_ch==3'h6    ),
    .q              (ch6_wrFIFO_q                   ),
    .rdusedw        (ch6_wrFIFO_rdusedw             ),
    .aclr           (!DDR2_rst_n || ch6_wr_rst      )
);

//写FIFO通道7
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch7
(
    .wrclk          (ch7_wr_clk                     ),
    .wrreq          (ch7_wr_vld                     ),
    .data           (ch7_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wr_ack && wr_ch==3'h7    ),
    .q              (ch7_wrFIFO_q                   ),
    .rdusedw        (ch7_wrFIFO_rdusedw             ),
    .aclr           (!DDR2_rst_n  || ch7_wr_rst     )
);

//根据通道选择写入相应FIFO的数据
//---------------------------------------------------
assign burst_wr_data = (wr_ch == 3'h7) ? ch7_wrFIFO_q :
                       (wr_ch == 3'h6) ? ch6_wrFIFO_q :
                       (wr_ch == 3'h5) ? ch5_wrFIFO_q :
                       (wr_ch == 3'h4) ? ch4_wrFIFO_q :
                       (wr_ch == 3'h3) ? ch3_wrFIFO_q :
                       (wr_ch == 3'h2) ? ch2_wrFIFO_q :
                       (wr_ch == 3'h1) ? ch1_wrFIFO_q :
                                         ch0_wrFIFO_q ;
//读FIFO通道0
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch0
(
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rd_ack && rd_ch==3'h0    ),
    .data           (burst_rd_data                  ),
    .rdclk          (ch0_rd_clk                     ),
    .rdreq          (ch0_rd_req                     ),
    .q              (ch0_rd_data                    ),  //输出到端口0
    .wrusedw        (ch0_rdFIFO_wrusedw             ),
    .aclr           (!DDR2_rst_n || ch0_rd_rst      )
);

//读FIFO通道1
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch1
(
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rd_ack && rd_ch==3'h1    ),
    .data           (burst_rd_data                  ),
    .rdclk          (ch1_rd_clk                     ),
    .rdreq          (ch1_rd_req                     ),
    .q              (ch1_rd_data                    ),  //输出到端口1
    .wrusedw        (ch1_rdFIFO_wrusedw             ),
    .aclr           (!DDR2_rst_n || ch1_rd_rst      )
);

//读FIFO通道2
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch2
(
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rd_ack && rd_ch==3'h2    ),
    .data           (burst_rd_data                  ),
    .rdclk          (ch2_rd_clk                     ),
    .rdreq          (ch2_rd_req                     ),
    .q              (ch2_rd_data                    ),  //输出到端口2
    .wrusedw        (ch2_rdFIFO_wrusedw             ),
    .aclr           (!DDR2_rst_n || ch2_rd_rst      )
);

//读FIFO通道3
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch3
(
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rd_ack && rd_ch==3'h3    ),
    .data           (burst_rd_data                  ),
    .rdclk          (ch3_rd_clk                     ),
    .rdreq          (ch3_rd_req                     ),
    .q              (ch3_rd_data                    ),  //输出到端口3
    .wrusedw        (ch3_rdFIFO_wrusedw             ),
    .aclr           (!DDR2_rst_n || ch3_rd_rst      )
);

//读FIFO通道4
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch4
(
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rd_ack && rd_ch==3'h4    ),
    .data           (burst_rd_data                  ),
    .rdclk          (ch4_rd_clk                     ),
    .rdreq          (ch4_rd_req                     ),
    .q              (ch4_rd_data                    ),  //输出到端口4
    .wrusedw        (ch4_rdFIFO_wrusedw             ),
    .aclr           (!DDR2_rst_n || ch4_rd_rst      )
);

//读FIFO通道5
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch5
(
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rd_ack && rd_ch==3'h5    ),
    .data           (burst_rd_data                  ),
    .rdclk          (ch5_rd_clk                     ),
    .rdreq          (ch5_rd_req                     ),
    .q              (ch5_rd_data                    ),  //输出到端口5
    .wrusedw        (ch5_rdFIFO_wrusedw             ),
    .aclr           (!DDR2_rst_n || ch5_rd_rst      )
);

//读FIFO通道6
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch6
(
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rd_ack && rd_ch==3'h6    ),
    .data           (burst_rd_data                  ),
    .rdclk          (ch6_rd_clk                     ),
    .rdreq          (ch6_rd_req                     ),
    .q              (ch6_rd_data                    ),  //输出到端口6
    .wrusedw        (ch6_rdFIFO_wrusedw             ),
    .aclr           (!DDR2_rst_n || ch6_rd_rst      )
);

//读FIFO通道7
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch7
(
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rd_ack && rd_ch==3'h7    ),
    .data           (burst_rd_data                  ),
    .rdclk          (ch7_rd_clk                     ),
    .rdreq          (ch7_rd_req                     ),
    .q              (ch7_rd_data                    ),  //输出到端口7
    .wrusedw        (ch7_rdFIFO_wrusedw             ),
    .aclr           (!DDR2_rst_n || ch7_rd_rst      )
);
//==========================================================================
//==    状态机
//==========================================================================
always @(posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        state <= IDLE;
    end
    else begin
        case(state)
            //--------------------------------------------------- 空闲
            IDLE:   begin
                            state = ARBIT;
                    end
            //--------------------------------------------------- 仲裁
            ARBIT:  begin
                        if((ch0_en && ch0_wrFIFO_rdusedw >= burst_len) || (ch1_en && ch1_wrFIFO_rdusedw >= burst_len) ||
                           (ch2_en && ch2_wrFIFO_rdusedw >= burst_len) || (ch3_en && ch3_wrFIFO_rdusedw >= burst_len) ||
                           (ch4_en && ch4_wrFIFO_rdusedw >= burst_len) || (ch5_en && ch5_wrFIFO_rdusedw >= burst_len) ||
                           (ch6_en && ch6_wrFIFO_rdusedw >= burst_len) || (ch7_en && ch7_wrFIFO_rdusedw >= burst_len))
                            state = WR;
                        else if((ch0_en && ch0_rdFIFO_wrusedw < burst_len) || (ch1_en && ch1_rdFIFO_wrusedw < burst_len) || 
                                (ch2_en && ch2_rdFIFO_wrusedw < burst_len) || (ch3_en && ch3_rdFIFO_wrusedw < burst_len) ||
                                (ch4_en && ch4_rdFIFO_wrusedw < burst_len) || (ch5_en && ch5_rdFIFO_wrusedw < burst_len) || 
                                (ch6_en && ch6_rdFIFO_wrusedw < burst_len) || (ch7_en && ch7_rdFIFO_wrusedw < burst_len))
                            state = RD;
                        else if(!ch0_en && !ch1_en && !ch2_en && !ch3_en && 
                                !ch4_en && !ch5_en && !ch6_en && !ch7_en)
                            state = IDLE;
                    end
            //--------------------------------------------------- 写
            WR:     begin
                        if(burst_wr_done)
                            state = WR_DONE;
                    end
            //--------------------------------------------------- 写完成
            WR_DONE:begin
                            state = IDLE;
                    end
            //--------------------------------------------------- 读
            RD:     begin
                        if(burst_rd_done)
                            state = RD_DONE;
                    end
            //--------------------------------------------------- 读完成
            RD_DONE:begin
                            state = IDLE;
                    end
            default:        state = IDLE;
        endcase
    end
end
//==========================================================================
//==    读写请求
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        burst_wr_req <= 1'b0;
    end
    else if(burst_wr_req == 1'b0 && state == WR) begin
        burst_wr_req <= 1'b1;
    end
    else if(burst_wr_req == 1'b1 && state == WR && burst_wr_done) begin
        burst_wr_req <= 1'b0;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        burst_rd_req <= 1'b0;
    end
    else if(burst_rd_req == 1'b0 && state == RD) begin
        burst_rd_req <= 1'b1;
    end
    else if(burst_rd_req == 1'b1 && state == RD && burst_rd_done) begin
        burst_rd_req <= 1'b0;
    end
end
//==========================================================================
//==    读写地址设计
//==========================================================================
//通道0
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch0_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch0_wr_rst) begin
        ch0_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(wr_ch == 3'h0 && state == WR && burst_wr_done) begin
        if(ch0_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch0_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch0_wr_addr <= ch0_wr_addr + burst_len;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch0_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch0_rd_rst) begin
        ch0_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(rd_ch == 3'h0 && state == RD && burst_rd_done) begin
        if(ch0_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch0_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch0_rd_addr <= ch0_rd_addr + burst_len;
    end
end

//通道1
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch1_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch1_wr_rst) begin
        ch1_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(wr_ch == 3'h1 && state == WR && burst_wr_done) begin
        if(ch1_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch1_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch1_wr_addr <= ch1_wr_addr + burst_len;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch1_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch1_rd_rst) begin
        ch1_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(rd_ch == 3'h1 && state == RD && burst_rd_done) begin
        if(ch1_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch1_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch1_rd_addr <= ch1_rd_addr + burst_len;
    end
end

//通道2
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch2_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch2_wr_rst) begin
        ch2_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(wr_ch == 3'h2 && state == WR && burst_wr_done) begin
        if(ch2_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch2_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch2_wr_addr <= ch2_wr_addr + burst_len;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch2_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch2_rd_rst) begin
        ch2_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(rd_ch == 3'h2 && state == RD && burst_rd_done) begin
        if(ch2_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch2_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch2_rd_addr <= ch2_rd_addr + burst_len;
    end
end

//通道3
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch3_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch3_wr_rst) begin
        ch3_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(wr_ch == 3'h3 && state == WR && burst_wr_done) begin
        if(ch3_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch3_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch3_wr_addr <= ch3_wr_addr + burst_len;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch3_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch3_rd_rst) begin
        ch3_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(rd_ch == 3'h3 && state == RD && burst_rd_done) begin
        if(ch3_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch3_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch3_rd_addr <= ch3_rd_addr + burst_len;
    end
end

//通道4
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch4_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch4_wr_rst) begin
        ch4_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(wr_ch == 3'h4 && state == WR && burst_wr_done) begin
        if(ch4_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch4_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch4_wr_addr <= ch4_wr_addr + burst_len;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch4_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch4_rd_rst) begin
        ch4_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(rd_ch == 3'h4 && state == RD && burst_rd_done) begin
        if(ch4_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch4_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch4_rd_addr <= ch4_rd_addr + burst_len;
    end
end

//通道5
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch5_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch5_wr_rst) begin
        ch5_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(wr_ch == 3'h5 && state == WR && burst_wr_done) begin
        if(ch5_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch5_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch5_wr_addr <= ch5_wr_addr + burst_len;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch5_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch5_rd_rst) begin
        ch5_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(rd_ch == 3'h5 && state == RD && burst_rd_done) begin
        if(ch5_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch5_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch5_rd_addr <= ch5_rd_addr + burst_len;
    end
end

//通道6
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch6_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch6_wr_rst) begin
        ch6_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(wr_ch == 3'h6 && state == WR && burst_wr_done) begin
        if(ch6_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch6_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch6_wr_addr <= ch6_wr_addr + burst_len;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch6_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch6_rd_rst) begin
        ch6_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(rd_ch == 3'h6 && state == RD && burst_rd_done) begin
        if(ch6_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch6_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch6_rd_addr <= ch6_rd_addr + burst_len;
    end
end

//通道7
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch7_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch7_wr_rst) begin
        ch7_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(wr_ch == 3'h7 && state == WR && burst_wr_done) begin
        if(ch7_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch7_wr_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch7_wr_addr <= ch7_wr_addr + burst_len;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch7_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(ch7_rd_rst) begin
        ch7_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
    end
    else if(rd_ch == 3'h7 && state == RD && burst_rd_done) begin
        if(ch7_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch7_rd_addr <= min_addr[LOCAL_ADDR_W-3:0];
        else
            ch7_rd_addr <= ch7_rd_addr + burst_len;
    end
end
//==========================================================================
//==    乒乓操作
//==========================================================================
//通道0
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch0_wr_addr_msb <= 1'b0;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h0 && state == WR && burst_wr_done) begin
        if(ch0_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch0_wr_addr_msb <= ~ch0_wr_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch0_wr_addr_msb <= 1'b0;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch0_rd_addr_msb <= 1'b1;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h0 && state == RD && burst_rd_done) begin
        if(ch0_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len && ch0_rd_addr_msb == ch0_wr_addr_msb)
            ch0_rd_addr_msb <= ~ch0_rd_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch0_rd_addr_msb <= 1'b0;
    end
end

//通道1
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch1_wr_addr_msb <= 1'b0;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h1 && state == WR && burst_wr_done) begin
        if(ch1_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch1_wr_addr_msb <= ~ch1_wr_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch1_wr_addr_msb <= 1'b0;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch1_rd_addr_msb <= 1'b1;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h1 && state == RD && burst_rd_done) begin
        if(ch1_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len && ch1_rd_addr_msb == ch1_wr_addr_msb)
            ch1_rd_addr_msb <= ~ch1_rd_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch1_rd_addr_msb <= 1'b0;
    end
end

//通道2
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch2_wr_addr_msb <= 1'b0;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h2 && state == WR && burst_wr_done) begin
        if(ch2_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch2_wr_addr_msb <= ~ch2_wr_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch2_wr_addr_msb <= 1'b0;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch2_rd_addr_msb <= 1'b1;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h2 && state == RD && burst_rd_done) begin
        if(ch2_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len && ch2_rd_addr_msb == ch2_wr_addr_msb)
            ch2_rd_addr_msb <= ~ch2_rd_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch2_rd_addr_msb <= 1'b0;
    end
end

//通道3
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch3_wr_addr_msb <= 1'b0;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h3 && state == WR && burst_wr_done) begin
        if(ch3_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch3_wr_addr_msb <= ~ch3_wr_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch3_wr_addr_msb <= 1'b0;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch3_rd_addr_msb <= 1'b1;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h3 && state == RD && burst_rd_done) begin
        if(ch3_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len && ch3_rd_addr_msb == ch3_wr_addr_msb)
            ch3_rd_addr_msb <= ~ch3_rd_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch3_rd_addr_msb <= 1'b0;
    end
end

//通道4
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch4_wr_addr_msb <= 1'b0;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h4 && state == WR && burst_wr_done) begin
        if(ch4_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch4_wr_addr_msb <= ~ch4_wr_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch4_wr_addr_msb <= 1'b0;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch4_rd_addr_msb <= 1'b1;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h4 && state == RD && burst_rd_done) begin
        if(ch4_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len && ch4_rd_addr_msb == ch4_wr_addr_msb)
            ch4_rd_addr_msb <= ~ch4_rd_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch4_rd_addr_msb <= 1'b0;
    end
end

//通道5
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch5_wr_addr_msb <= 1'b0;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h5 && state == WR && burst_wr_done) begin
        if(ch5_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch5_wr_addr_msb <= ~ch5_wr_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch5_wr_addr_msb <= 1'b0;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch5_rd_addr_msb <= 1'b1;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h5 && state == RD && burst_rd_done) begin
        if(ch5_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len && ch5_rd_addr_msb == ch5_wr_addr_msb)
            ch5_rd_addr_msb <= ~ch5_rd_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch5_rd_addr_msb <= 1'b0;
    end
end

//通道6
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch6_wr_addr_msb <= 1'b0;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h6 && state == WR && burst_wr_done) begin
        if(ch6_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch6_wr_addr_msb <= ~ch6_wr_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch6_wr_addr_msb <= 1'b0;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch6_rd_addr_msb <= 1'b1;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h6 && state == RD && burst_rd_done) begin
        if(ch6_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len && ch6_rd_addr_msb == ch6_wr_addr_msb)
            ch6_rd_addr_msb <= ~ch6_rd_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch6_rd_addr_msb <= 1'b0;
    end
end

//通道7
//---------------------------------------------------
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch7_wr_addr_msb <= 1'b0;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h7 && state == WR && burst_wr_done) begin
        if(ch7_wr_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len)
            ch7_wr_addr_msb <= ~ch7_wr_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch7_wr_addr_msb <= 1'b0;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        ch7_rd_addr_msb <= 1'b1;
    end
    else if(pingpang_vld == 1'b1 && wr_ch == 3'h7 && state == RD && burst_rd_done) begin
        if(ch7_rd_addr == max_addr[LOCAL_ADDR_W-3:2] - burst_len && ch7_rd_addr_msb == ch7_wr_addr_msb)
            ch7_rd_addr_msb <= ~ch7_rd_addr_msb;
    end
    else if(pingpang_vld == 1'b0) begin
        ch7_rd_addr_msb <= 1'b0;
    end
end
//==========================================================================
//==    地址拼接
//==========================================================================
assign burst_wr_addr = (wr_ch == 3'h7) ? {ch7_addr,ch7_wr_addr_msb,ch7_wr_addr} :
                       (wr_ch == 3'h6) ? {ch6_addr,ch6_wr_addr_msb,ch6_wr_addr} :
                       (wr_ch == 3'h5) ? {ch5_addr,ch5_wr_addr_msb,ch5_wr_addr} :
                       (wr_ch == 3'h4) ? {ch4_addr,ch4_wr_addr_msb,ch4_wr_addr} :
                       (wr_ch == 3'h3) ? {ch3_addr,ch3_wr_addr_msb,ch3_wr_addr} :
                       (wr_ch == 3'h2) ? {ch2_addr,ch2_wr_addr_msb,ch2_wr_addr} :
                       (wr_ch == 3'h1) ? {ch1_addr,ch1_wr_addr_msb,ch1_wr_addr} :
                                         {ch0_addr,ch0_wr_addr_msb,ch0_wr_addr} ;
                                              
assign burst_rd_addr = (rd_ch == 3'h7) ? {ch7_addr,ch7_rd_addr_msb,ch7_rd_addr} :
                       (rd_ch == 3'h6) ? {ch6_addr,ch6_rd_addr_msb,ch6_rd_addr} :
                       (rd_ch == 3'h5) ? {ch5_addr,ch5_rd_addr_msb,ch5_rd_addr} :
                       (rd_ch == 3'h4) ? {ch4_addr,ch4_rd_addr_msb,ch4_rd_addr} :
                       (rd_ch == 3'h3) ? {ch3_addr,ch3_rd_addr_msb,ch3_rd_addr} :
                       (rd_ch == 3'h2) ? {ch2_addr,ch2_rd_addr_msb,ch2_rd_addr} :
                       (rd_ch == 3'h1) ? {ch1_addr,ch1_rd_addr_msb,ch1_rd_addr} :
                                         {ch0_addr,ch0_rd_addr_msb,ch0_rd_addr} ;
                                             

endmodule

(3) DDR2_burst

DDR2_burst
//**************************************************************************
// *** 名称 : DDR2_burst.v
// *** 作者 : xianyu_FPGA
// *** 博客 : https://www.cnblogs.com/xianyufpga/
// *** 日期 : 2020年6月
// *** 描述 : 完成一次DDR2的突发读写
//**************************************************************************

module DDR2_burst
//============================< 参数 >======================================
#(
parameter MEM_DM_W              = 4                     ,   //DDR2 dm位宽
parameter MEM_DQS_W             = 4                     ,   //DDR2 dqs位宽
parameter MEM_BANK_W            = 3                     ,   //DDR2 bank位宽
parameter MEM_ADDR_W            = 13                    ,   //DDR2 地址位宽
parameter MEM_DQ_W              = 32                    ,   //DDR2 数据位宽,一片16两片32
//-------------------------------------------------------
parameter LOCAL_SIZE_W          = 3                     ,   //DDR2 IP核local_size位宽
parameter LOCAL_DATA_W          = 64                    ,   //DDR2 IP核数据位宽
parameter LOCAL_ADDR_W          = 25                        //DDR2 IP核地址位宽
)
//============================< 端口 >======================================
(
//DDR2 IP核接口 -----------------------------------------
input                           pll_ref_clk             ,   //DDR2 参考时钟
input                           global_reset_n          ,   //FPGA 全局复位
output                          phy_clk                 ,   //DDR2 工作时钟
output                          DDR2_rst_n              ,   //DDR2 同步复位
//突发读写接口 ------------------------------------------
input                           burst_rd_req            ,   //突发读请求
input                           burst_wr_req            ,   //突发写请求
input   [LOCAL_ADDR_W -3:0]     burst_rd_len            ,   //突发读长度
input   [LOCAL_ADDR_W -3:0]     burst_wr_len            ,   //突发写长度
input   [LOCAL_ADDR_W -1:0]     burst_rd_addr           ,   //突发读地址
input   [LOCAL_ADDR_W -1:0]     burst_wr_addr           ,   //突发写地址
output  [LOCAL_DATA_W -1:0]     burst_rd_data           ,   //突发读数据
input   [LOCAL_DATA_W -1:0]     burst_wr_data           ,   //突发写数据
output                          burst_rd_ack            ,   //突发读应答,连接FIFO
output                          burst_wr_ack            ,   //突发写应答,连接FIFO
output  reg                     burst_rd_done           ,   //突发读完成信号
output  reg                     burst_wr_done           ,   //突发写完成信号
//DDR2 芯片接口 -----------------------------------------
output                          mem_odt                 ,   //DDR2 片上终结信号
output                          mem_cs_n                ,   //DDR2 片选信号
output                          mem_cke                 ,   //DDR2 时钟使能信号
output  [MEM_ADDR_W   -1:0]     mem_addr                ,   //DDR2 地址总线
output  [MEM_BANK_W   -1:0]     mem_ba                  ,   //DDR2 BANK信号
output                          mem_ras_n               ,   //DDR2 行地址选择信号
output                          mem_cas_n               ,   //DDR2 列地址选择信号
output                          mem_we_n                ,   //DDR2 写使能信号
output  [MEM_DM_W     -1:0]     mem_dm                  ,   //DDR2 数据掩膜信号
inout                           mem_clk                 ,   //DDR2 时钟信号
inout                           mem_clk_n               ,   //DDR2 时钟反相信号
inout   [MEM_DQ_W     -1:0]     mem_dq                  ,   //DDR2 数据总线
inout   [MEM_DQS_W    -1:0]     mem_dqs                     //DDR2 数据源同步信号
);
//============================< 信号 >======================================
reg     [LOCAL_ADDR_W -1:0]     local_address           ;   //DDR2 IP核地址总线
wire                            local_write_req         ;   //DDR2 IP核写请求信号
wire                            local_read_req          ;   //DDR2 IP核读请求信号
wire                            local_burstbegin        ;   //DDR2 IP核突发起始信号
wire    [LOCAL_DATA_W -1:0]     local_wdata             ;   //DDR2 IP核写数据总线
reg     [LOCAL_SIZE_W -1:0]     local_size              ;   //DDR2 IP核突发大小
wire                            local_ready             ;   //DDR2 IP核准备好信号
wire    [LOCAL_DATA_W -1:0]     local_rdata             ;   //DDR2 IP核读数据总线
wire                            local_rdata_valid       ;   //DDR2 IP核读数据有效信号
wire                            reset_phy_clk_n         ;   //DDR2 IP核复位后同步信号
wire                            local_init_done         ;   //DDR2 IP核初始化完成信号
//-------------------------------------------------------
reg     [4:0]                   state                   ;   //状态机
reg     [LOCAL_ADDR_W -1:0]     wr_len                  ;   //读突发长度
reg     [LOCAL_ADDR_W -1:0]     rd_len                  ;   //写突发长度
reg     [LOCAL_ADDR_W -1:0]     wr_addr_cnt             ;   //写地址计数器
reg     [LOCAL_ADDR_W -1:0]     wr_burst_cnt            ;   //一次突发写内的数据计数
reg     [LOCAL_ADDR_W -1:0]     rd_addr_cnt             ;   //读地址计数器
reg     [LOCAL_ADDR_W -1:0]     rd_data_cnt             ;   //读数据计数器
//============================< 参数 >======================================
localparam   WR_SIZE            = 2                     ;   //总线写突发
localparam   RD_SIZE            = 2                     ;   //总线读突发
//------------------------------------------------------
localparam   IDLE               = 5'b00001              ;   //空闲状态
localparam   ARBIT              = 5'b00010              ;   //仲裁状态
localparam   WR                 = 5'b00100              ;   //写状态
localparam   RD_ADDR            = 5'b01000              ;   //读状态
localparam   RD_WAIT            = 5'b10000              ;   //读等待状态
//==========================================================================
//==    DDR2 IP核,PLL 100Mhz,DDR2 166.7Mhz,Full Rate
//==========================================================================
DDR2 u_DDR2
(
    .pll_ref_clk                (pll_ref_clk            ),  //DDR2 参考时钟
    .global_reset_n             (global_reset_n         ),  //全局复位信号
    .soft_reset_n               (1'b1                   ),  //软复位信号
    .local_address              (local_address          ),  //DDR2 IP核地址总线
    .local_write_req            (local_write_req        ),  //DDR2 IP核写请求信号
    .local_read_req             (local_read_req         ),  //DDR2 IP核读请求信号
    .local_burstbegin           (local_burstbegin       ),  //DDR2 IP核突发起始信号
    .local_wdata                (local_wdata            ),  //DDR2 IP核写数据总线
    .local_be                   (8'b1111_1111           ),  //DDR2 IP核字节使能信号
    .local_size                 (local_size             ),  //DDR2 IP核突发大小
    .local_ready                (local_ready            ),  //DDR2 IP核准备好信号
    .local_rdata                (local_rdata            ),  //DDR2 IP核读数据总线
    .local_rdata_valid          (local_rdata_valid      ),  //DDR2 IP核读数据有效信号
    .local_refresh_ack          (                       ),  //DDR2 IP核自刷新应答信号
    .local_init_done            (local_init_done        ),  //DDR2 IP核初始化完成信号
    //---------------------------------------------------
    .mem_odt                    (mem_odt                ),  //DDR2片上终结信号
    .mem_cs_n                   (mem_cs_n               ),  //DDR2片选信号
    .mem_cke                    (mem_cke                ),  //DDR2时钟使能信号
    .mem_addr                   (mem_addr               ),  //DDR2地址总线
    .mem_ba                     (mem_ba                 ),  //DDR2组地址信号
    .mem_ras_n                  (mem_ras_n              ),  //DDR2行地址选择信
    .mem_cas_n                  (mem_cas_n              ),  //DDR2列地址选择信
    .mem_we_n                   (mem_we_n               ),  //DDR2写使能信号
    .mem_dm                     (mem_dm                 ),  //DDR2数据掩膜信号
    .mem_clk                    (mem_clk                ),  //DDR2时钟信号
    .mem_clk_n                  (mem_clk_n              ),  //DDR2时钟反相信号
    .mem_dq                     (mem_dq                 ),  //DDR2数据总线
    .mem_dqs                    (mem_dqs                ),  //DDR2数据源同步信号
    .phy_clk                    (phy_clk                ),  //DDR2 IP核工作时钟
    .reset_phy_clk_n            (reset_phy_clk_n        ),  //DDR2 IP核同步后的复位信号
    .reset_request_n            (                       ),  //DDR2 IP核复位请求信号
    .aux_full_rate_clk          (                       ),  //DDR2 IP核全速率时钟
    .aux_half_rate_clk          (                       )   //DDR2 IP核半速率时钟
);

//本模块复位信号
assign DDR2_rst_n = reset_phy_clk_n & local_init_done;
//==========================================================================
//==    状态机
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        state <= IDLE;
        burst_wr_done <= 1'b0;
        burst_rd_done <= 1'b0;
    end
    else begin
        case(state)
            IDLE:   begin
                        burst_wr_done <= 1'b0;
                        burst_rd_done <= 1'b0;
                        state <= ARBIT;
                    end
            ARBIT:  begin
                        if(burst_wr_req) begin
                            state <= WR;
                        end
                        else if(burst_rd_req) begin
                            state <= RD_ADDR;
                        end
                    end
            WR:     begin
                        if(wr_addr_cnt + wr_burst_cnt >= wr_len - 1 && local_ready) begin
                            state <= IDLE;
                            burst_wr_done <= 1'b1;
                        end
                    end
            RD_ADDR:begin
                        if(rd_addr_cnt >= rd_len - RD_SIZE && local_ready) begin
                            state <= RD_WAIT;
                        end
                    end
            RD_WAIT:begin
                        if(rd_data_cnt >= rd_len - 1) begin
                            state <= IDLE;
                            burst_rd_done <= 1'b1;
                        end
                    end
            default:
                        state <= IDLE;
        endcase
    end
end
//------------------------------------------ 状态机名称,测试用
reg [55:0] state_name; //1个字符8位宽
always @(*) begin
    case(state)
        IDLE    :   state_name = "IDLE";
        ARBIT   :   state_name = "ARBIT";
        WR      :   state_name = "WR";
        RD_ADDR :   state_name = "RD_ADDR";
        RD_WAIT :   state_name = "RD_WAIT";
        default :   state_name = "IDLE";
    endcase
end
//==========================================================================
//==    在进入读状态前锁存读突发长度
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        wr_len <= 'h0;
    end
    else if(state == ARBIT && burst_wr_req) begin
        wr_len <= burst_wr_len;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        rd_len <= 'h0;
    end
    else if(state == ARBIT && burst_rd_req) begin
        rd_len <= burst_rd_len;
    end
end
//==========================================================================
//==    写突发的数据计数:0101010101
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        wr_burst_cnt <= 'h0;
    end
    else if(state == WR && local_ready) begin
        if(wr_burst_cnt >= WR_SIZE - 1)
            wr_burst_cnt <= 'h0;
        else
            wr_burst_cnt <= wr_burst_cnt + 'h1;
    end
end
//==========================================================================
//==    每凑齐2个数据则地址+2
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        wr_addr_cnt <= 'h0;
    end
    else if(state == WR && local_ready) begin
        if(wr_addr_cnt + wr_burst_cnt >= wr_len - 1)
            wr_addr_cnt <= 'h0;
        else if(wr_burst_cnt >= WR_SIZE - 1)
            wr_addr_cnt <= wr_addr_cnt + WR_SIZE;    
    end
end
//==========================================================================
//==    每给出读指令时读地址+2
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        rd_addr_cnt <= 'h0;
    end
    else if(state == RD_ADDR && local_ready) begin
        if(rd_addr_cnt >= rd_len - RD_SIZE)
            rd_addr_cnt <= 'h0;
        else
            rd_addr_cnt <= rd_addr_cnt + RD_SIZE;
    end
end
//==========================================================================
//==    每读出一个数据地址递+1
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        rd_data_cnt <= 'h0;
    end
    else if(local_rdata_valid) begin
        if(rd_data_cnt >= rd_len - 1)
            rd_data_cnt <= 'h0;
        else
            rd_data_cnt <= rd_data_cnt + 'h1;
    end
end
//==========================================================================
//==    锁存local_size并在最后一次读写时如果不足突发大小则更改local_size为不足的大小
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        local_size <= 'h0;
    end
    else if(state == ARBIT && burst_wr_req) begin
        local_size <= (burst_wr_len >= WR_SIZE) ? WR_SIZE : burst_wr_len;
    end
    else if(state == ARBIT && burst_rd_req) begin
        local_size <= (burst_rd_len >= RD_SIZE) ? RD_SIZE : burst_rd_len;
    end
    else if(state == WR && wr_burst_cnt == WR_SIZE - 1 && wr_addr_cnt + {WR_SIZE,1'b0} > wr_len && local_ready) begin
        local_size <= wr_len - wr_addr_cnt - WR_SIZE;
    end
    else if(state == RD_ADDR && rd_addr_cnt + {RD_SIZE,1'b0} > rd_len && local_ready) begin
        local_size <= rd_len - rd_addr_cnt - RD_SIZE;
    end
end
//==========================================================================
//==    锁存local_address,并且在完成一次突发读写时递增读写地址
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        local_address <= 'h0;
    end
    else if(state == ARBIT && burst_wr_req) begin
        local_address <= burst_wr_addr;
    end
    else if(state == ARBIT && burst_rd_req) begin
        local_address <= burst_rd_addr;
    end
    else if(state == WR && (wr_burst_cnt == WR_SIZE - 1) && local_ready) begin
        local_address <= local_address + WR_SIZE;
    end
    else if(state == RD_ADDR && local_ready) begin
        local_address <= local_address + RD_SIZE;
    end
end
//==========================================================================
//==    其他信号
//==========================================================================
//burstbegin信号,随便怎么写都行,直接赋值1'b1也能跑
assign local_burstbegin = (state == WR || state == RD_ADDR) ? 1'b1 : 1'b0;

//写数据
assign local_wdata = burst_wr_data;

//写应答,即写FIFO的读使能
assign burst_wr_ack = (state == WR && local_ready) ? 1'b1 : 1'b0;

//读数据
assign burst_rd_data = local_rdata;

//读应答,即读FIFO的写使能
assign burst_rd_ack = local_rdata_valid;

//写请求
assign local_write_req = (state == WR) ? 1'b1 : 1'b0;

//读请求
assign local_read_req = (state == RD_ADDR) ? 1'b1 : 1'b0;



endmodule

2、DDR2_8port v2

(1) inst

inst
//==========================================================================
//==                        DDR2_8port
//==========================================================================
DDR2_8port  u_DDR2_8port
(
    //时钟和复位 ------------------------------------
    .pll_ref_clk            (clk_100m               ),  //DDR2输入时钟
    .global_reset_n         (sys_rst_n              ),  //全局复位信号
    //DDR2端口 -------------------------------------- 
    .mem_odt                (mem_odt                ),  //DDR2片上终结信号
    .mem_cs_n               (mem_cs_n               ),  //DDR2片选信号
    .mem_cke                (mem_cke                ),  //DDR2时钟使能信号
    .mem_addr               (mem_addr               ),  //DDR2地址总线
    .mem_ba                 (mem_ba                 ),  //DDR2BANK信号
    .mem_ras_n              (mem_ras_n              ),  //DDR2行地址选择信号
    .mem_cas_n              (mem_cas_n              ),  //DDR2列地址选择信号
    .mem_we_n               (mem_we_n               ),  //DDR2写使能信号
    .mem_dm                 (mem_dm                 ),  //DDR2数据掩膜信号
    .mem_clk                (mem_clk                ),  //DDR2时钟信号
    .mem_clk_n              (mem_clk_n              ),  //DDR2时钟反相信号
    .mem_dq                 (mem_dq                 ),  //DDR2数据总线
    .mem_dqs                (mem_dqs                ),  //DDR2数据源同步信号
    //DDR2控制 --------------------------------------     
    .DDR2_init_done         (                       ),  //DDR2 IP核初始化信号
    .DDR2_phy_clk           (                       ),  //DDR2 IP核输出时钟
    .DDR2_phy_rst_n         (                       ),  //DDR2 IP核输出的同步复位信号
    //通道0 ----------------------------------------- 
    .ch0_addr               (3'h0                   ),  //通道0地址
    .ch0_width              (CH_WIDTH               ),  //通道0宽度
    .ch0_height             (CH_HEIGHT              ),  //通道0高度
    .ch0_wr_clk             (ch0_clk                ),  //通道0写时钟
    .ch0_wr_data            (ch0_data               ),  //通道0输入数据
    .ch0_wr_vld             (ch0_vld                ),  //通道0输入数据有效信号
    .ch0_wr_vsync           (ch0_vsync              ),  //通道0场信号(写)
    .ch0_wr_en              (1'b1                   ),  //通道0写使能
    .ch0_rd_clk             (clk_VGA                ),  //通道0读时钟
    .ch0_rd_data            (ch0_VGA_din            ),  //通道0输出数据
    .ch0_rd_req             (ch0_VGA_req            ),  //通道0输出请求
    .ch0_rd_vsync           (VGA_vsync              ),  //通道0场信号(读)
    .ch0_rd_en              (1'b1                   ),  //通道0读使能
    //通道1 ----------------------------------------- 
    .ch1_addr               (3'h1                   ),  //通道1地址
    .ch1_width              (CH_WIDTH               ),  //通道1宽度
    .ch1_height             (CH_HEIGHT              ),  //通道1高度
    .ch1_wr_clk             (ch1_clk                ),  //通道1写时钟
    .ch1_wr_data            (ch1_data               ),  //通道1输入数据
    .ch1_wr_vld             (ch1_vld                ),  //通道1输入数据有效信号
    .ch1_wr_vsync           (ch1_vsync              ),  //通道1场信号(写)
    .ch1_wr_en              (1'b1                   ),  //通道1写使能
    .ch1_rd_clk             (clk_VGA                ),  //通道1读时钟
    .ch1_rd_data            (ch1_VGA_din            ),  //通道1输出数据
    .ch1_rd_req             (ch1_VGA_req            ),  //通道1输出请求
    .ch1_rd_vsync           (VGA_vsync              ),  //通道1场信号(读)
    .ch1_rd_en              (1'b1                   ),  //通道1读使能
    //通道2 ----------------------------------------- 
    .ch2_addr               (3'h2                   ),  //通道2地址
    .ch2_width              (CH_WIDTH               ),  //通道2宽度
    .ch2_height             (CH_HEIGHT              ),  //通道2高度
    .ch2_wr_clk             (ch2_clk                ),  //通道2写时钟
    .ch2_wr_data            (ch2_data               ),  //通道2输入数据
    .ch2_wr_vld             (ch2_vld                ),  //通道2输入数据有效信号
    .ch2_wr_vsync           (ch2_vsync              ),  //通道2场信号(写)
    .ch2_wr_en              (1'b1                   ),  //通道2写使能
    .ch2_rd_clk             (clk_VGA                ),  //通道2读时钟
    .ch2_rd_data            (ch2_VGA_din            ),  //通道2输出数据
    .ch2_rd_req             (ch2_VGA_req            ),  //通道2输出请求
    .ch2_rd_vsync           (VGA_vsync              ),  //通道2场信号(读)
    .ch2_rd_en              (1'b1                   ),  //通道2读使能
    //通道3 ----------------------------------------- 
    .ch3_addr               (3'h3                   ),  //通道3地址
    .ch3_width              (CH_WIDTH               ),  //通道3宽度
    .ch3_height             (CH_HEIGHT              ),  //通道3高度
    .ch3_wr_clk             (ch3_clk                ),  //通道3写时钟
    .ch3_wr_data            (ch3_data               ),  //通道3输入数据
    .ch3_wr_vld             (ch3_vld                ),  //通道3输入数据有效信号
    .ch3_wr_vsync           (ch3_vsync              ),  //通道3场信号(写)
    .ch3_wr_en              (1'b1                   ),  //通道3写使能
    .ch3_rd_clk             (clk_VGA                ),  //通道3读时钟
    .ch3_rd_data            (ch3_VGA_din            ),  //通道3输出数据
    .ch3_rd_req             (ch3_VGA_req            ),  //通道3输出请求
    .ch3_rd_vsync           (VGA_vsync              ),  //通道3场信号(读)
    .ch3_rd_en              (1'b1                   ),  //通道3读使能
    //通道4 ----------------------------------------- 
    .ch4_addr               (3'h4                   ),  //通道4地址
    .ch4_width              (CH_WIDTH               ),  //通道4宽度
    .ch4_height             (CH_HEIGHT              ),  //通道4高度
    .ch4_wr_clk             (ch4_clk                ),  //通道4写时钟
    .ch4_wr_data            (ch4_data               ),  //通道4输入数据
    .ch4_wr_vld             (ch4_vld                ),  //通道4输入数据有效信号
    .ch4_wr_vsync           (ch4_vsync              ),  //通道4场信号(写)
    .ch4_wr_en              (1'b1                   ),  //通道4写使能
    .ch4_rd_clk             (clk_VGA                ),  //通道4读时钟
    .ch4_rd_data            (ch4_VGA_din            ),  //通道4输出数据
    .ch4_rd_req             (ch4_VGA_req            ),  //通道4输出请求
    .ch4_rd_vsync           (VGA_vsync              ),  //通道4场信号(读)
    .ch4_rd_en              (1'b1                   ),  //通道4读使能
    //通道5 ----------------------------------------- 
    .ch5_addr               (3'h5                   ),  //通道5地址
    .ch5_width              (CH_WIDTH               ),  //通道5宽度
    .ch5_height             (CH_HEIGHT              ),  //通道5高度
    .ch5_wr_clk             (ch5_clk                ),  //通道5写时钟
    .ch5_wr_data            (ch5_data               ),  //通道5输入数据
    .ch5_wr_vld             (ch5_vld                ),  //通道5输入数据有效信号
    .ch5_wr_vsync           (ch5_vsync              ),  //通道5场信号(写)
    .ch5_wr_en              (1'b1                   ),  //通道5写使能
    .ch5_rd_clk             (clk_VGA                ),  //通道5读时钟
    .ch5_rd_data            (ch5_VGA_din            ),  //通道5输出数据
    .ch5_rd_req             (ch5_VGA_req            ),  //通道5输出请求
    .ch5_rd_vsync           (VGA_vsync              ),  //通道5场信号(读)
    .ch5_rd_en              (1'b1                   ),  //通道5读使能
    //通道6 ----------------------------------------- 
    .ch6_addr               (3'h6                   ),  //通道6地址
    .ch6_width              (CH_WIDTH               ),  //通道6宽度
    .ch6_height             (CH_HEIGHT              ),  //通道6高度
    .ch6_wr_clk             (ch6_clk                ),  //通道6写时钟
    .ch6_wr_data            (ch6_data               ),  //通道6输入数据
    .ch6_wr_vld             (ch6_vld                ),  //通道6输入数据有效信号
    .ch6_wr_vsync           (ch6_vsync              ),  //通道6场信号(写)
    .ch6_wr_en              (1'b1                   ),  //通道6写使能
    .ch6_rd_clk             (clk_VGA                ),  //通道6读时钟
    .ch6_rd_data            (ch6_VGA_din            ),  //通道6输出数据
    .ch6_rd_req             (ch6_VGA_req            ),  //通道6输出请求
    .ch6_rd_vsync           (VGA_vsync              ),  //通道6场信号(读)
    .ch6_rd_en              (1'b1                   ),  //通道6读使能
    //通道7 ----------------------------------------- 
    .ch7_addr               (3'h7                   ),  //通道7地址
    .ch7_width              (CH_WIDTH               ),  //通道7宽度
    .ch7_height             (CH_HEIGHT              ),  //通道7高度
    .ch7_wr_clk             (ch7_clk                ),  //通道7写时钟
    .ch7_wr_data            (ch7_data               ),  //通道7输入数据
    .ch7_wr_vld             (ch7_vld                ),  //通道7输入数据有效信号
    .ch7_wr_vsync           (ch7_vsync              ),  //通道7场信号(写)
    .ch7_wr_en              (1'b1                   ),  //通道7写使能
    .ch7_rd_clk             (clk_VGA                ),  //通道7读时钟
    .ch7_rd_data            (ch7_VGA_din            ),  //通道7输出数据
    .ch7_rd_req             (ch7_VGA_req            ),  //通道7输出请求
    .ch7_rd_vsync           (VGA_vsync              ),  //通道7场信号(读)
    .ch7_rd_en              (1'b1                   )   //通道7读使能
);

(2) DDR2_port

DDR2_8port
`include "DDR2_param.v"
//**************************************************************************
// *** 名称 : DDR2_8port.v
// *** 作者 : xianyu_FPGA
// *** 博客 : https://www.cnblogs.com/xianyufpga/
// *** 日期 : 2020年6月
// *** 描述 : 多通道视频读写突发的控制模块,每个通道都可以选择是否使用,
//            行地址有10位,列地址有10位,wrFIFO深度1024,rdFIFO深度256,
//            位宽为64,综合考虑后,单通道最大支持1024x1024.
//**************************************************************************

module DDR2_8port
//============================< 端口 >======================================
(
//时钟和复位 ----------------------------------------
input                           pll_ref_clk         ,   //DDR2输入时钟
input                           global_reset_n      ,   //全局复位信号
//DDR2端口 ------------------------------------------
output                          mem_odt             ,   //DDR2片上终结信号
output                          mem_cs_n            ,   //DDR2片选信号
output                          mem_cke             ,   //DDR2时钟使能信号
output  [`MEM_ADDR_W    -1:0]   mem_addr            ,   //DDR2地址总线
output  [`MEM_BANK_W    -1:0]   mem_ba              ,   //DDR2BANK信号
output                          mem_ras_n           ,   //DDR2行地址选择信号
output                          mem_cas_n           ,   //DDR2列地址选择信号
output                          mem_we_n            ,   //DDR2写使能信号
output  [`MEM_DM_W      -1:0]   mem_dm              ,   //DDR2数据掩膜信号
inout                           mem_clk             ,   //DDR2时钟信号
inout                           mem_clk_n           ,   //DDR2时钟反相信号
inout   [`MEM_DQ_W      -1:0]   mem_dq              ,   //DDR2数据总线
inout   [`MEM_DQS_W     -1:0]   mem_dqs             ,   //DDR2数据源同步信号
//DDR2控制 ------------------------------------------ 
output                          DDR2_init_done      ,   //DDR2 IP核初始化信号
output                          DDR2_phy_clk        ,   //DDR2 IP核输出时钟
output                          DDR2_phy_rst_n      ,   //DDR2 IP核输出的同步复位信号
//通道0 ---------------------------------------------
input   [ 2:0]                  ch0_addr            ,   //通道0地址
input   [15:0]                  ch0_width           ,   //通道0宽度
input   [15:0]                  ch0_height          ,   //通道0高度
input                           ch0_wr_clk          ,   //通道0写时钟
input   [15:0]                  ch0_wr_data         ,   //通道0输入数据
input                           ch0_wr_vld          ,   //通道0输入数据有效信号
input                           ch0_wr_vsync        ,   //通道0场信号(写)
input                           ch0_wr_en           ,   //通道0写使能
input                           ch0_rd_clk          ,   //通道0读时钟
output  [15:0]                  ch0_rd_data         ,   //通道0输出数据
input                           ch0_rd_req          ,   //通道0输出请求
input                           ch0_rd_vsync        ,   //通道0场信号(读)
input                           ch0_rd_en           ,   //通道0读使能
//通道1 ---------------------------------------------
input   [ 2:0]                  ch1_addr            ,   //通道1地址
input   [15:0]                  ch1_width           ,   //通道1宽度
input   [15:0]                  ch1_height          ,   //通道1高度
input                           ch1_wr_clk          ,   //通道1写时钟
input   [15:0]                  ch1_wr_data         ,   //通道1输入数据
input                           ch1_wr_vld          ,   //通道1输入数据有效信号
input                           ch1_wr_vsync        ,   //通道1场信号(写)
input                           ch1_wr_en           ,   //通道1写使能
input                           ch1_rd_clk          ,   //通道1读时钟
output  [15:0]                  ch1_rd_data         ,   //通道1输出数据
input                           ch1_rd_req          ,   //通道1输出请求
input                           ch1_rd_vsync        ,   //通道1场信号(读)
input                           ch1_rd_en           ,   //通道1读使能
//通道2 ---------------------------------------------
input   [ 2:0]                  ch2_addr            ,   //通道2地址
input   [15:0]                  ch2_width           ,   //通道2宽度
input   [15:0]                  ch2_height          ,   //通道2高度
input                           ch2_wr_clk          ,   //通道2写时钟
input   [15:0]                  ch2_wr_data         ,   //通道2输入数据
input                           ch2_wr_vld          ,   //通道2输入数据有效信号
input                           ch2_wr_vsync        ,   //通道2场信号(写)
input                           ch2_wr_en           ,   //通道2写使能
input                           ch2_rd_clk          ,   //通道2读时钟
output  [15:0]                  ch2_rd_data         ,   //通道2输出数据
input                           ch2_rd_req          ,   //通道2输出请求
input                           ch2_rd_vsync        ,   //通道2场信号(读)
input                           ch2_rd_en           ,   //通道2读使能
//通道3 ---------------------------------------------
input   [ 2:0]                  ch3_addr            ,   //通道3地址
input   [15:0]                  ch3_width           ,   //通道3宽度
input   [15:0]                  ch3_height          ,   //通道3高度
input                           ch3_wr_clk          ,   //通道3写时钟
input   [15:0]                  ch3_wr_data         ,   //通道3输入数据
input                           ch3_wr_vld          ,   //通道3输入数据有效信号
input                           ch3_wr_vsync        ,   //通道3场信号(写)
input                           ch3_wr_en           ,   //通道3写使能
input                           ch3_rd_clk          ,   //通道3读时钟
output  [15:0]                  ch3_rd_data         ,   //通道3输出数据
input                           ch3_rd_req          ,   //通道3输出请求
input                           ch3_rd_vsync        ,   //通道3场信号(读)
input                           ch3_rd_en           ,   //通道3读使能
//通道4 ---------------------------------------------
input   [ 2:0]                  ch4_addr            ,   //通道4地址
input   [15:0]                  ch4_width           ,   //通道4宽度
input   [15:0]                  ch4_height          ,   //通道4高度
input                           ch4_wr_clk          ,   //通道4写时钟
input   [15:0]                  ch4_wr_data         ,   //通道4输入数据
input                           ch4_wr_vld          ,   //通道4输入数据有效信号
input                           ch4_wr_vsync        ,   //通道4场信号(写)
input                           ch4_wr_en           ,   //通道4写使能
input                           ch4_rd_clk          ,   //通道4读时钟
output  [15:0]                  ch4_rd_data         ,   //通道4输出数据
input                           ch4_rd_req          ,   //通道4输出请求
input                           ch4_rd_vsync        ,   //通道4场信号(读)
input                           ch4_rd_en           ,   //通道4读使能
//通道5 ---------------------------------------------
input   [ 2:0]                  ch5_addr            ,   //通道5地址
input   [15:0]                  ch5_width           ,   //通道5宽度
input   [15:0]                  ch5_height          ,   //通道5高度
input                           ch5_wr_clk          ,   //通道5写时钟
input   [15:0]                  ch5_wr_data         ,   //通道5输入数据
input                           ch5_wr_vld          ,   //通道5输入数据有效信号
input                           ch5_wr_vsync        ,   //通道5场信号(写)
input                           ch5_wr_en           ,   //通道5写使能
input                           ch5_rd_clk          ,   //通道5读时钟
output  [15:0]                  ch5_rd_data         ,   //通道5输出数据
input                           ch5_rd_req          ,   //通道5输出请求
input                           ch5_rd_vsync        ,   //通道5场信号(读)
input                           ch5_rd_en           ,   //通道5读使能
//通道6 ---------------------------------------------
input   [ 2:0]                  ch6_addr            ,   //通道6地址
input   [15:0]                  ch6_width           ,   //通道6宽度
input   [15:0]                  ch6_height          ,   //通道6高度
input                           ch6_wr_clk          ,   //通道6写时钟
input   [15:0]                  ch6_wr_data         ,   //通道6输入数据
input                           ch6_wr_vld          ,   //通道6输入数据有效信号
input                           ch6_wr_vsync        ,   //通道6场信号(写)
input                           ch6_wr_en           ,   //通道6写使能
input                           ch6_rd_clk          ,   //通道6读时钟
output  [15:0]                  ch6_rd_data         ,   //通道6输出数据
input                           ch6_rd_req          ,   //通道6输出请求
input                           ch6_rd_vsync        ,   //通道6场信号(读)
input                           ch6_rd_en           ,   //通道6读使能
//通道7 ---------------------------------------------
input   [ 2:0]                  ch7_addr            ,   //通道7地址
input   [15:0]                  ch7_width           ,   //通道7宽度
input   [15:0]                  ch7_height          ,   //通道7高度
input                           ch7_wr_clk          ,   //通道7写时钟
input   [15:0]                  ch7_wr_data         ,   //通道7输入数据
input                           ch7_wr_vld          ,   //通道7输入数据有效信号
input                           ch7_wr_vsync        ,   //通道7场信号(写)
input                           ch7_wr_en           ,   //通道7写使能
input                           ch7_rd_clk          ,   //通道7读时钟
output  [15:0]                  ch7_rd_data         ,   //通道7输出数据
input                           ch7_rd_req          ,   //通道7输出请求
input                           ch7_rd_vsync        ,   //通道7场信号(读)
input                           ch7_rd_en               //通道7读使能
);
//============================< 信号 >======================================
wire    [13:0]                  burst_len           ;   //读写突发长度
wire    [`LOCAL_DATA_W  -1:0]   burst_rddata        ;   //读突发数据
wire    [`LOCAL_DATA_W  -1:0]   burst_wrdata        ;   //写突发数据
wire                            burst_rdack         ;   //读突发应答信号
wire                            burst_wrack         ;   //写突发应答信号
wire                            burst_rddone        ;   //突发读完成信号
wire                            burst_wrdone        ;   //突发写完成信号
//---------------------------------------------------
wire                            phy_clk             ;   //DDR2 IP核工作时钟
wire                            reset_phy_clk_n     ;   //DDR2 IP核同步后的复位信号
wire                            local_init_done     ;   //DDR2 IP核初始化完成信号
wire                            rst_n               ;   //本模块使用的复位信号
//---------------------------------------------------
reg                             ch0_wr_vsync_r      ;   //通道0场信号打一拍
reg                             ch0_wr_rst          ;   //通道0场复位信号
reg                             ch1_wr_vsync_r      ;   //通道1场信号打一拍
reg                             ch1_wr_rst          ;   //通道1场复位信号
reg                             ch2_wr_vsync_r      ;   //通道2场信号打一拍
reg                             ch2_wr_rst          ;   //通道2场复位信号
reg                             ch3_wr_vsync_r      ;   //通道3场信号打一拍
reg                             ch3_wr_rst          ;   //通道3场复位信号
reg                             ch4_wr_vsync_r      ;   //通道4场信号打一拍
reg                             ch4_wr_rst          ;   //通道4场复位信号
reg                             ch5_wr_vsync_r      ;   //通道5场信号打一拍
reg                             ch5_wr_rst          ;   //通道5场复位信号
reg                             ch6_wr_vsync_r      ;   //通道6场信号打一拍
reg                             ch6_wr_rst          ;   //通道6场复位信号
reg                             ch7_wr_vsync_r      ;   //通道7场信号打一拍
reg                             ch7_wr_rst          ;   //通道7场复位信号
//---------------------------------------------------
reg                             ch0_rd_vsync_r      ;   //通道0场信号打一拍
reg                             ch0_rd_rst          ;   //通道0场复位信号
reg                             ch1_rd_vsync_r      ;   //通道1场信号打一拍
reg                             ch1_rd_rst          ;   //通道1场复位信号
reg                             ch2_rd_vsync_r      ;   //通道2场信号打一拍
reg                             ch2_rd_rst          ;   //通道2场复位信号
reg                             ch3_rd_vsync_r      ;   //通道3场信号打一拍
reg                             ch3_rd_rst          ;   //通道3场复位信号
reg                             ch4_rd_vsync_r      ;   //通道4场信号打一拍
reg                             ch4_rd_rst          ;   //通道4场复位信号
reg                             ch5_rd_vsync_r      ;   //通道5场信号打一拍
reg                             ch5_rd_rst          ;   //通道5场复位信号
reg                             ch6_rd_vsync_r      ;   //通道6场信号打一拍
reg                             ch6_rd_rst          ;   //通道6场复位信号
reg                             ch7_rd_vsync_r      ;   //通道7场信号打一拍
reg                             ch7_rd_rst          ;   //通道7场复位信号
//---------------------------------------------------
wire    [`LOCAL_DATA_W  -1:0]   ch0_wrFIFO_q        ;   //通道0读数据
wire    [`LOCAL_DATA_W  -1:0]   ch1_wrFIFO_q        ;   //通道1读数据
wire    [`LOCAL_DATA_W  -1:0]   ch2_wrFIFO_q        ;   //通道2读数据
wire    [`LOCAL_DATA_W  -1:0]   ch3_wrFIFO_q        ;   //通道3读数据
wire    [`LOCAL_DATA_W  -1:0]   ch4_wrFIFO_q        ;   //通道4读数据
wire    [`LOCAL_DATA_W  -1:0]   ch5_wrFIFO_q        ;   //通道5读数据
wire    [`LOCAL_DATA_W  -1:0]   ch6_wrFIFO_q        ;   //通道6读数据
wire    [`LOCAL_DATA_W  -1:0]   ch7_wrFIFO_q        ;   //通道7读数据
wire    [ 8:0]                  ch0_wrFIFO_rdusedw  ;   //通道0写FIFO剩余数据个数
wire    [ 8:0]                  ch1_wrFIFO_rdusedw  ;   //通道1写FIFO剩余数据个数
wire    [ 8:0]                  ch2_wrFIFO_rdusedw  ;   //通道2写FIFO剩余数据个数
wire    [ 8:0]                  ch3_wrFIFO_rdusedw  ;   //通道3写FIFO剩余数据个数
wire    [ 8:0]                  ch4_wrFIFO_rdusedw  ;   //通道4写FIFO剩余数据个数
wire    [ 8:0]                  ch5_wrFIFO_rdusedw  ;   //通道5写FIFO剩余数据个数
wire    [ 8:0]                  ch6_wrFIFO_rdusedw  ;   //通道6写FIFO剩余数据个数
wire    [ 8:0]                  ch7_wrFIFO_rdusedw  ;   //通道7写FIFO剩余数据个数
wire    [ 8:0]                  ch0_rdFIFO_wrusedw  ;   //通道0读FIFO剩余数据个数
wire    [ 8:0]                  ch1_rdFIFO_wrusedw  ;   //通道1读FIFO剩余数据个数
wire    [ 8:0]                  ch2_rdFIFO_wrusedw  ;   //通道2读FIFO剩余数据个数
wire    [ 8:0]                  ch3_rdFIFO_wrusedw  ;   //通道3读FIFO剩余数据个数
wire    [ 8:0]                  ch4_rdFIFO_wrusedw  ;   //通道4读FIFO剩余数据个数
wire    [ 8:0]                  ch5_rdFIFO_wrusedw  ;   //通道5读FIFO剩余数据个数
wire    [ 8:0]                  ch6_rdFIFO_wrusedw  ;   //通道6读FIFO剩余数据个数
wire    [ 8:0]                  ch7_rdFIFO_wrusedw  ;   //通道7读FIFO剩余数据个数
//---------------------------------------------------
reg     [ 3:0]                  fsm_cs              ;   //状态机的当前状态
reg     [ 3:0]                  fsm_ns              ;   //状态机的下一个状态
//---------------------------------------------------
reg     [ 2:0]                  wrchannel           ;   //写通道
reg     [ 2:0]                  rdchannel           ;   //读通道
//---------------------------------------------------
reg     [15:0]                  ch0_wr_vcnt         ;   //通道0写行计数   
reg     [15:0]                  ch1_wr_vcnt         ;   //通道1写行计数
reg     [15:0]                  ch2_wr_vcnt         ;   //通道2写行计数
reg     [15:0]                  ch3_wr_vcnt         ;   //通道3写行计数
reg     [15:0]                  ch4_wr_vcnt         ;   //通道4写行计数   
reg     [15:0]                  ch5_wr_vcnt         ;   //通道5写行计数
reg     [15:0]                  ch6_wr_vcnt         ;   //通道6写行计数
reg     [15:0]                  ch7_wr_vcnt         ;   //通道7写行计数
reg     [15:0]                  ch0_rd_vcnt         ;   //通道0读行计数
reg     [15:0]                  ch1_rd_vcnt         ;   //通道1读行计数
reg     [15:0]                  ch2_rd_vcnt         ;   //通道2读行计数
reg     [15:0]                  ch3_rd_vcnt         ;   //通道3读行计数
reg     [15:0]                  ch4_rd_vcnt         ;   //通道4读行计数
reg     [15:0]                  ch5_rd_vcnt         ;   //通道5读行计数
reg     [15:0]                  ch6_rd_vcnt         ;   //通道6读行计数
reg     [15:0]                  ch7_rd_vcnt         ;   //通道7读行计数
reg     [`LOCAL_ADDR_W  -1:0]   burst_wraddr        ;   //写突发地址
reg     [`LOCAL_ADDR_W  -1:0]   burst_rdaddr        ;   //读突发地址
//---------------------------------------------------
reg                             burst_wrreq         ;   //突发写请求
reg                             burst_rdreq         ;   //突发读请求
//---------------------------------------------------
reg     [ 1:0]                  ch0_wraddr_msb      ;   //通道0乒乓操作写分区
reg     [ 1:0]                  ch0_rdaddr_msb      ;   //通道0乒乓操作读分区
reg     [ 1:0]                  ch1_wraddr_msb      ;   //通道1乒乓操作写分区
reg     [ 1:0]                  ch1_rdaddr_msb      ;   //通道1乒乓操作读分区
reg     [ 1:0]                  ch2_wraddr_msb      ;   //通道2乒乓操作写分区
reg     [ 1:0]                  ch2_rdaddr_msb      ;   //通道2乒乓操作读分区
reg     [ 1:0]                  ch3_wraddr_msb      ;   //通道3乒乓操作写分区
reg     [ 1:0]                  ch3_rdaddr_msb      ;   //通道3乒乓操作读分区
reg     [ 1:0]                  ch4_wraddr_msb      ;   //通道4乒乓操作写分区
reg     [ 1:0]                  ch4_rdaddr_msb      ;   //通道4乒乓操作读分区
reg     [ 1:0]                  ch5_wraddr_msb      ;   //通道5乒乓操作写分区
reg     [ 1:0]                  ch5_rdaddr_msb      ;   //通道5乒乓操作读分区
reg     [ 1:0]                  ch6_wraddr_msb      ;   //通道6乒乓操作写分区
reg     [ 1:0]                  ch6_rdaddr_msb      ;   //通道6乒乓操作读分区
reg     [ 1:0]                  ch7_wraddr_msb      ;   //通道7乒乓操作写分区
reg     [ 1:0]                  ch7_rdaddr_msb      ;   //通道7乒乓操作读分区
//============================< 参数 >======================================
parameter   FSM_IDLE            = 4'h0              ;   //空闲状态
parameter   FSM_ARBIT           = 4'h1              ;   //仲裁状态
parameter   FSM_WRITE           = 4'h2              ;   //写状态
parameter   FSM_WREND           = 4'h3              ;   //写完成状态
parameter   FSM_READ            = 4'h4              ;   //读状态
parameter   FSM_RDEND           = 4'h5              ;   //读完成状态
//==========================================================================
//==    DDR2突发读写模块,实现一段长度的突发读写
//==========================================================================
DDR2_burst u_DDR2_burst
(
    //IP核引出接口 ----------------------------------
    .pll_ref_clk            (pll_ref_clk            ),  //DDR2 参考时钟 
    .global_reset_n         (global_reset_n         ),  //全局复位信号,连接外部复位
    .phy_clk                (phy_clk                ),  //DDR2 IP核工作时钟
    .reset_phy_clk_n        (reset_phy_clk_n        ),  //DDR2 IP核同步后的复位信号  
    .local_init_done        (local_init_done        ),  //DDR2 IP核初始化完成信号
    //突发读写接口 ----------------------------------
    .burst_rdreq            (burst_rdreq            ),  //突发读请求
    .burst_wrreq            (burst_wrreq            ),  //突发写请求
    .burst_rdlen            (burst_len              ),  //突发读长度
    .burst_wrlen            (burst_len              ),  //突发写长度
    .burst_rdaddr           (burst_rdaddr           ),  //突发读地址
    .burst_wraddr           (burst_wraddr           ),  //突发写地址
    .burst_rddata           (burst_rddata           ),  //突发读数据
    .burst_wrdata           (burst_wrdata           ),  //突发写数据
    .burst_rdack            (burst_rdack            ),  //突发读应答,连接FIFO
    .burst_wrack            (burst_wrack            ),  //突发写应答,连接FIFO
    .burst_rddone           (burst_rddone           ),  //突发读完成信号
    .burst_wrdone           (burst_wrdone           ),  //突发写完成信号   
    //芯片接口 --------------------------------------
    .mem_odt                (mem_odt                ),  //DDR2片上终结信号
    .mem_cs_n               (mem_cs_n               ),  //DDR2片选信号
    .mem_cke                (mem_cke                ),  //DDR2时钟使能信号
    .mem_addr               (mem_addr               ),  //DDR2地址总线  
    .mem_ba                 (mem_ba                 ),  //DDR2bank信号
    .mem_ras_n              (mem_ras_n              ),  //DDR2行地址选择信号
    .mem_cas_n              (mem_cas_n              ),  //DDR2列地址选择信号
    .mem_we_n               (mem_we_n               ),  //DDR2写使能信号
    .mem_dm                 (mem_dm                 ),  //DDR2数据掩膜信号
    .mem_clk                (mem_clk                ),  //DDR2时钟信号
    .mem_clk_n              (mem_clk_n              ),  //DDR2时钟反相信号
    .mem_dq                 (mem_dq                 ),  //DDR2数据总线
    .mem_dqs                (mem_dqs                )   //DDR2数据源同步信号
);
//==========================================================================
//==    简单信号
//==========================================================================
//读写突发长度,16和64互转,长度/4
assign burst_len = ch0_width[15:2];

//DDR2初始化完成信号
assign DDR2_init_done = local_init_done;

//DDR2输出时钟信号
assign DDR2_phy_clk = phy_clk;

//DDR2复位信号
assign DDR2_phy_rst_n = reset_phy_clk_n;

//本模块复合复位信号
assign rst_n = reset_phy_clk_n && local_init_done;
//==========================================================================
//==    利用写侧场同步信号设计写FIFO的异步复位
//==========================================================================
//通道0
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch0_wr_vsync_r <= 1'h0;
    end
    else begin
        ch0_wr_vsync_r <= ch0_wr_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch0_wr_rst <= 1'h0;
    end
    else if(!ch0_wr_vsync_r && ch0_wr_vsync) begin
        ch0_wr_rst <= 1'b1;
    end
    else begin
        ch0_wr_rst <= 1'b0;
    end
end

//通道1
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch1_wr_vsync_r <= 1'h0;
    end
    else begin
        ch1_wr_vsync_r <= ch1_wr_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch1_wr_rst <= 1'h0;
    end
    else if(!ch1_wr_vsync_r && ch1_wr_vsync) begin
        ch1_wr_rst <= 1'b1;
    end
    else begin
        ch1_wr_rst <= 1'b0;
    end
end

//通道2
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch2_wr_vsync_r <= 1'h0;
    end
    else begin
        ch2_wr_vsync_r <= ch2_wr_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch2_wr_rst <= 1'h0;
    end
    else if(!ch2_wr_vsync_r && ch2_wr_vsync) begin
        ch2_wr_rst <= 1'b1;
    end
    else begin
        ch2_wr_rst <= 1'b0;
    end
end

//通道3
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch3_wr_vsync_r <= 1'h0;
    end
    else begin
        ch3_wr_vsync_r <= ch3_wr_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch3_wr_rst <= 1'h0;
    end
    else if(!ch3_wr_vsync_r && ch3_wr_vsync) begin
        ch3_wr_rst <= 1'b1;
    end
    else begin
        ch3_wr_rst <= 1'b0;
    end
end

//通道4
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch4_wr_vsync_r <= 1'h0;
    end
    else begin
        ch4_wr_vsync_r <= ch4_wr_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch4_wr_rst <= 1'h0;
    end
    else if(!ch4_wr_vsync_r && ch4_wr_vsync) begin
        ch4_wr_rst <= 1'b1;
    end
    else begin
        ch4_wr_rst <= 1'b0;
    end
end

//通道5
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch5_wr_vsync_r <= 1'h0;
    end
    else begin
        ch5_wr_vsync_r <= ch5_wr_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch5_wr_rst <= 1'h0;
    end
    else if(!ch5_wr_vsync_r && ch5_wr_vsync) begin
        ch5_wr_rst <= 1'b1;
    end
    else begin
        ch5_wr_rst <= 1'b0;
    end
end

//通道6
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch6_wr_vsync_r <= 1'h0;
    end
    else begin
        ch6_wr_vsync_r <= ch6_wr_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch6_wr_rst <= 1'h0;
    end
    else if(!ch6_wr_vsync_r && ch6_wr_vsync) begin
        ch6_wr_rst <= 1'b1;
    end
    else begin
        ch6_wr_rst <= 1'b0;
    end
end

//通道7
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch7_wr_vsync_r <= 1'h0;
    end
    else begin
        ch7_wr_vsync_r <= ch7_wr_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch7_wr_rst <= 1'h0;
    end
    else if(!ch7_wr_vsync_r && ch7_wr_vsync) begin
        ch7_wr_rst <= 1'b1;
    end
    else begin
        ch7_wr_rst <= 1'b0;
    end
end
//==========================================================================
//==    利用读侧场同步信号设计读FIFO的异步复位
//==========================================================================
//通道0
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch0_rd_vsync_r <= 1'h0;
    end
    else begin
        ch0_rd_vsync_r <= ch0_rd_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch0_rd_rst <= 1'h0;
    end
    else if(!ch0_rd_vsync_r && ch0_rd_vsync) begin
        ch0_rd_rst <= 1'b1;
    end
    else begin
        ch0_rd_rst <= 1'b0;
    end
end

//通道1
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch1_rd_vsync_r <= 1'h0;
    end
    else begin
        ch1_rd_vsync_r <= ch1_rd_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch1_rd_rst <= 1'h0;
    end
    else if(!ch1_rd_vsync_r && ch1_rd_vsync) begin
        ch1_rd_rst <= 1'b1;
    end
    else begin
        ch1_rd_rst <= 1'b0;
    end
end

//通道2
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch2_rd_vsync_r <= 1'h0;
    end
    else begin
        ch2_rd_vsync_r <= ch2_rd_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch2_rd_rst <= 1'h0;
    end
    else if(!ch2_rd_vsync_r && ch2_rd_vsync) begin
        ch2_rd_rst <= 1'b1;
    end
    else begin
        ch2_rd_rst <= 1'b0;
    end
end

//通道3
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch3_rd_vsync_r <= 1'h0;
    end
    else begin
        ch3_rd_vsync_r <= ch3_rd_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch3_rd_rst <= 1'h0;
    end
    else if(!ch3_rd_vsync_r && ch3_rd_vsync) begin
        ch3_rd_rst <= 1'b1;
    end
    else begin
        ch3_rd_rst <= 1'b0;
    end
end

//通道4
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch4_rd_vsync_r <= 1'h0;
    end
    else begin
        ch4_rd_vsync_r <= ch4_rd_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch4_rd_rst <= 1'h0;
    end
    else if(!ch4_rd_vsync_r && ch4_rd_vsync) begin
        ch4_rd_rst <= 1'b1;
    end
    else begin
        ch4_rd_rst <= 1'b0;
    end
end

//通道5
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch5_rd_vsync_r <= 1'h0;
    end
    else begin
        ch5_rd_vsync_r <= ch5_rd_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch5_rd_rst <= 1'h0;
    end
    else if(!ch5_rd_vsync_r && ch5_rd_vsync) begin
        ch5_rd_rst <= 1'b1;
    end
    else begin
        ch5_rd_rst <= 1'b0;
    end
end

//通道6
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch6_rd_vsync_r <= 1'h0;
    end
    else begin
        ch6_rd_vsync_r <= ch6_rd_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch6_rd_rst <= 1'h0;
    end
    else if(!ch6_rd_vsync_r && ch6_rd_vsync) begin
        ch6_rd_rst <= 1'b1;
    end
    else begin
        ch6_rd_rst <= 1'b0;
    end
end

//通道7
//---------------------------------------------------
//打拍
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch7_rd_vsync_r <= 1'h0;
    end
    else begin
        ch7_rd_vsync_r <= ch7_rd_vsync;
    end
end

//场起始信号当作场复位信号,高有效  
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch7_rd_rst <= 1'h0;
    end
    else if(!ch7_rd_vsync_r && ch7_rd_vsync) begin
        ch7_rd_rst <= 1'b1;
    end
    else begin
        ch7_rd_rst <= 1'b0;
    end
end
//==========================================================================
//==    FIFO
//==========================================================================
//写FIFO通道0
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch0
(
    .aclr           (!rst_n || ch0_wr_rst            ),
    .data           (ch0_wr_data                     ),
    .rdclk          (phy_clk                         ),
    .rdreq          (burst_wrack && wrchannel==3'h0  ),
    .wrclk          (ch0_wr_clk                      ),
    .wrreq          (ch0_wr_vld                      ),
    .q              (ch0_wrFIFO_q                    ),
    .rdempty        (                                ),
    .rdusedw        (ch0_wrFIFO_rdusedw              ),
    .wrfull         (                                ),
    .wrusedw        (                                )
);

//写FIFO通道1
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch1
(
    .aclr           (!rst_n || ch1_wr_rst           ),
    .data           (ch1_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wrack && wrchannel==3'h1 ),
    .wrclk          (ch1_wr_clk                     ),
    .wrreq          (ch1_wr_vld                     ),
    .q              (ch1_wrFIFO_q                   ),
    .rdempty        (                               ),
    .rdusedw        (ch1_wrFIFO_rdusedw             ),
    .wrfull         (                               ),
    .wrusedw        (                               )
);

//写FIFO通道2
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch2
(
    .aclr           (!rst_n || ch2_wr_rst           ),
    .data           (ch2_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wrack && wrchannel==3'h2 ),
    .wrclk          (ch2_wr_clk                     ),
    .wrreq          (ch2_wr_vld                     ),
    .q              (ch2_wrFIFO_q                   ),
    .rdempty        (                               ),
    .rdusedw        (ch2_wrFIFO_rdusedw             ),
    .wrfull         (                               ),
    .wrusedw        (                               )
);

//写FIFO通道3
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch3
(
    .aclr           (!rst_n || ch3_wr_rst           ),
    .data           (ch3_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wrack && wrchannel==3'h3 ),
    .wrclk          (ch3_wr_clk                     ),
    .wrreq          (ch3_wr_vld                     ),
    .q              (ch3_wrFIFO_q                   ),
    .rdempty        (                               ),
    .rdusedw        (ch3_wrFIFO_rdusedw             ),
    .wrfull         (                               ),
    .wrusedw        (                               )
);

//写FIFO通道4
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch4
(
    .aclr           (!rst_n || ch4_wr_rst            ),
    .data           (ch4_wr_data                     ),
    .rdclk          (phy_clk                         ),
    .rdreq          (burst_wrack && wrchannel==3'h4  ),
    .wrclk          (ch4_wr_clk                      ),
    .wrreq          (ch4_wr_vld                      ),
    .q              (ch4_wrFIFO_q                    ),
    .rdempty        (                                ),
    .rdusedw        (ch4_wrFIFO_rdusedw              ),
    .wrfull         (                                ),
    .wrusedw        (                                )
);

//写FIFO通道5
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch5
(
    .aclr           (!rst_n || ch5_wr_rst           ),
    .data           (ch5_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wrack && wrchannel==3'h5 ),
    .wrclk          (ch5_wr_clk                     ),
    .wrreq          (ch5_wr_vld                     ),
    .q              (ch5_wrFIFO_q                   ),
    .rdempty        (                               ),
    .rdusedw        (ch5_wrFIFO_rdusedw             ),
    .wrfull         (                               ),
    .wrusedw        (                               )
);

//写FIFO通道6
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch6
(
    .aclr           (!rst_n || ch6_wr_rst           ),
    .data           (ch6_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wrack && wrchannel==3'h6 ),
    .wrclk          (ch6_wr_clk                     ),
    .wrreq          (ch6_wr_vld                     ),
    .q              (ch6_wrFIFO_q                   ),
    .rdempty        (                               ),
    .rdusedw        (ch6_wrFIFO_rdusedw             ),
    .wrfull         (                               ),
    .wrusedw        (                               )
);

//写FIFO通道7
//---------------------------------------------------
wrFIFO_wr16_rd64_1024 wrFIFO_ch7
(
    .aclr           (!rst_n || ch7_wr_rst           ),
    .data           (ch7_wr_data                    ),
    .rdclk          (phy_clk                        ),
    .rdreq          (burst_wrack && wrchannel==3'h7 ),
    .wrclk          (ch7_wr_clk                     ),
    .wrreq          (ch7_wr_vld                     ),
    .q              (ch7_wrFIFO_q                   ),
    .rdempty        (                               ),
    .rdusedw        (ch7_wrFIFO_rdusedw             ),
    .wrfull         (                               ),
    .wrusedw        (                               )
);

//根据通道选择写入相应FIFO的数据
//---------------------------------------------------
assign burst_wrdata = (wrchannel == 3'h7) ? ch7_wrFIFO_q :
                      (wrchannel == 3'h6) ? ch6_wrFIFO_q :
                      (wrchannel == 3'h5) ? ch5_wrFIFO_q :
                      (wrchannel == 3'h4) ? ch4_wrFIFO_q :
                      (wrchannel == 3'h3) ? ch3_wrFIFO_q :
                      (wrchannel == 3'h2) ? ch2_wrFIFO_q :
                      (wrchannel == 3'h1) ? ch1_wrFIFO_q :
                                            ch0_wrFIFO_q ;

//读FIFO通道0
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch0
(
    .aclr           (!rst_n || ch0_rd_rst           ),
    .data           (burst_rddata                   ),
    .rdclk          (ch0_rd_clk                     ),
    .rdreq          (ch0_rd_req                     ),
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rdack && rdchannel==3'h0 ),
    .q              (ch0_rd_data                    ),  //输出到端口
    .rdempty        (                               ),
    .rdusedw        (                               ),
    .wrfull         (                               ),
    .wrusedw        (ch0_rdFIFO_wrusedw             )
);

//读FIFO通道1
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch1
(
    .aclr           (!rst_n || ch1_rd_rst           ),
    .data           (burst_rddata                   ),
    .rdclk          (ch1_rd_clk                     ),
    .rdreq          (ch1_rd_req                     ),
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rdack && rdchannel==3'h1 ),
    .q              (ch1_rd_data                    ),  //输出到端口
    .rdempty        (                               ),
    .rdusedw        (                               ),
    .wrfull         (                               ),
    .wrusedw        (ch1_rdFIFO_wrusedw             )
);

//读FIFO通道2
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch2
(
    .aclr           (!rst_n || ch2_rd_rst           ),
    .data           (burst_rddata                   ),
    .rdclk          (ch2_rd_clk                     ),
    .rdreq          (ch2_rd_req                     ),
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rdack && rdchannel==3'h2 ),
    .q              (ch2_rd_data                    ),  //输出到端口
    .rdempty        (                               ),
    .rdusedw        (                               ),
    .wrfull         (                               ),
    .wrusedw        (ch2_rdFIFO_wrusedw             )
);

//读FIFO通道3
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch3
(
    .aclr           (!rst_n || ch3_rd_rst           ),
    .data           (burst_rddata                   ),
    .rdclk          (ch3_rd_clk                     ),
    .rdreq          (ch3_rd_req                     ),
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rdack && rdchannel==3'h3 ),
    .q              (ch3_rd_data                    ),  //输出到端口
    .rdempty        (                               ),
    .rdusedw        (                               ),
    .wrfull         (                               ),
    .wrusedw        (ch3_rdFIFO_wrusedw             )
);

//读FIFO通道4
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch4
(
    .aclr           (!rst_n || ch4_rd_rst           ),
    .data           (burst_rddata                   ),
    .rdclk          (ch4_rd_clk                     ),
    .rdreq          (ch4_rd_req                     ),
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rdack && rdchannel==3'h4 ),
    .q              (ch4_rd_data                    ),  //输出到端口
    .rdempty        (                               ),
    .rdusedw        (                               ),
    .wrfull         (                               ),
    .wrusedw        (ch4_rdFIFO_wrusedw             )
);

//读FIFO通道1
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch5
(
    .aclr           (!rst_n || ch5_rd_rst           ),
    .data           (burst_rddata                   ),
    .rdclk          (ch5_rd_clk                     ),
    .rdreq          (ch5_rd_req                     ),
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rdack && rdchannel==3'h5 ),
    .q              (ch5_rd_data                    ),  //输出到端口
    .rdempty        (                               ),
    .rdusedw        (                               ),
    .wrfull         (                               ),
    .wrusedw        (ch5_rdFIFO_wrusedw             )
);

//读FIFO通道6
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch6
(
    .aclr           (!rst_n || ch6_rd_rst           ),
    .data           (burst_rddata                   ),
    .rdclk          (ch6_rd_clk                     ),
    .rdreq          (ch6_rd_req                     ),
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rdack && rdchannel==3'h6 ),
    .q              (ch6_rd_data                    ),  //输出到端口
    .rdempty        (                               ),
    .rdusedw        (                               ),
    .wrfull         (                               ),
    .wrusedw        (ch6_rdFIFO_wrusedw             )
);

//读FIFO通道3
//---------------------------------------------------
rdFIFO_wr64_rd16_256 rdFIFO_ch7
(
    .aclr           (!rst_n || ch7_rd_rst           ),
    .data           (burst_rddata                   ),
    .rdclk          (ch7_rd_clk                     ),
    .rdreq          (ch7_rd_req                     ),
    .wrclk          (phy_clk                        ),
    .wrreq          (burst_rdack && rdchannel==3'h7 ),
    .q              (ch7_rd_data                    ),  //输出到端口
    .rdempty        (                               ),
    .rdusedw        (                               ),
    .wrfull         (                               ),
    .wrusedw        (ch7_rdFIFO_wrusedw             )
);
//==========================================================================
//==    状态机
//==========================================================================
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n)
        fsm_cs <= FSM_IDLE;
    else
        fsm_cs <= fsm_ns;
end

always @ (*) begin
    case(fsm_cs)
        //--------------------------------------------------- 空闲
        FSM_IDLE:
                        fsm_ns = FSM_ARBIT;
        //--------------------------------------------------- 仲裁
        FSM_ARBIT:
                    if((ch0_wr_en && ch0_wrFIFO_rdusedw >= burst_len) || (ch1_wr_en && ch1_wrFIFO_rdusedw >= burst_len) ||
                       (ch2_wr_en && ch2_wrFIFO_rdusedw >= burst_len) || (ch3_wr_en && ch3_wrFIFO_rdusedw >= burst_len) ||
                       (ch4_wr_en && ch4_wrFIFO_rdusedw >= burst_len) || (ch5_wr_en && ch5_wrFIFO_rdusedw >= burst_len) ||
                       (ch6_wr_en && ch6_wrFIFO_rdusedw >= burst_len) || (ch7_wr_en && ch7_wrFIFO_rdusedw >= burst_len))
                        fsm_ns = FSM_WRITE;
                    else if((ch0_rd_en && 9'd256 - ch0_rdFIFO_wrusedw >= burst_len) || (ch1_rd_en && 9'd256 - ch1_rdFIFO_wrusedw >= burst_len) || 
                            (ch2_rd_en && 9'd256 - ch2_rdFIFO_wrusedw >= burst_len) || (ch3_rd_en && 9'd256 - ch3_rdFIFO_wrusedw >= burst_len) ||
                            (ch4_rd_en && 9'd256 - ch4_rdFIFO_wrusedw >= burst_len) || (ch5_rd_en && 9'd256 - ch5_rdFIFO_wrusedw >= burst_len) || 
                            (ch6_rd_en && 9'd256 - ch6_rdFIFO_wrusedw >= burst_len) || (ch7_rd_en && 9'd256 - ch7_rdFIFO_wrusedw >= burst_len))
                        fsm_ns = FSM_READ;
                    else if(!ch0_wr_en && !ch1_wr_en && !ch2_wr_en && !ch3_wr_en && !ch4_wr_en && !ch5_wr_en && !ch6_wr_en && !ch7_wr_en &&
                            !ch0_rd_en && !ch1_rd_en && !ch2_rd_en && !ch3_rd_en && !ch4_rd_en && !ch5_rd_en && !ch6_rd_en && !ch7_rd_en)
                        fsm_ns = FSM_IDLE;
                    else
                        fsm_ns = fsm_cs;
        //--------------------------------------------------- 写
        FSM_WRITE:
                    if(burst_wrdone)
                        fsm_ns = FSM_WREND;
                    else
                        fsm_ns = fsm_cs;
        //--------------------------------------------------- 写完成
        FSM_WREND:
                        fsm_ns = FSM_IDLE;
        //--------------------------------------------------- 读
        FSM_READ:
                    if(burst_rddone)
                        fsm_ns = FSM_RDEND;
                    else
                        fsm_ns = fsm_cs;
        //--------------------------------------------------- 读完成
        FSM_RDEND:
                        fsm_ns = FSM_IDLE;
        default:
                        fsm_ns = FSM_IDLE;
            
    endcase
end
//==========================================================================
//==    根据FIFO的状态,选择读写操作通道
//==========================================================================
//写通道
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        wrchannel <= 3'h0;
    end
    else if(fsm_cs == FSM_ARBIT && ch0_wr_en && ch0_wrFIFO_rdusedw >= burst_len) begin
        wrchannel <= 3'h0;
    end
    else if(fsm_cs == FSM_ARBIT && ch1_wr_en && ch1_wrFIFO_rdusedw >= burst_len) begin
        wrchannel <= 3'h1;
    end
    else if(fsm_cs == FSM_ARBIT && ch2_wr_en && ch2_wrFIFO_rdusedw >= burst_len) begin
        wrchannel <= 3'h2;
    end
    else if(fsm_cs == FSM_ARBIT && ch3_wr_en && ch3_wrFIFO_rdusedw >= burst_len) begin
        wrchannel <= 3'h3;
    end
    else if(fsm_cs == FSM_ARBIT && ch4_wr_en && ch4_wrFIFO_rdusedw >= burst_len) begin
        wrchannel <= 3'h4;
    end
    else if(fsm_cs == FSM_ARBIT && ch5_wr_en && ch5_wrFIFO_rdusedw >= burst_len) begin
        wrchannel <= 3'h5;
    end
    else if(fsm_cs == FSM_ARBIT && ch6_wr_en && ch6_wrFIFO_rdusedw >= burst_len) begin
        wrchannel <= 3'h6;
    end
    else if(fsm_cs == FSM_ARBIT && ch7_wr_en && ch7_wrFIFO_rdusedw >= burst_len) begin
        wrchannel <= 3'h7;
    end
end

//读通道
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        rdchannel <= 3'h0;
    end
    else if(fsm_cs == FSM_ARBIT && ch0_rd_en && 9'd256 - ch0_rdFIFO_wrusedw >= burst_len) begin
        rdchannel <= 3'h0;
    end
    else if(fsm_cs == FSM_ARBIT && ch1_rd_en && 9'd256 - ch1_rdFIFO_wrusedw >= burst_len) begin
        rdchannel <= 3'h1;
    end
    else if(fsm_cs == FSM_ARBIT && ch2_rd_en && 9'd256 - ch2_rdFIFO_wrusedw >= burst_len) begin
        rdchannel <= 3'h2;
    end
    else if(fsm_cs == FSM_ARBIT && ch3_rd_en && 9'd256 - ch3_rdFIFO_wrusedw >= burst_len) begin
        rdchannel <= 3'h3;
    end
    else if(fsm_cs == FSM_ARBIT && ch4_rd_en && 9'd256 - ch4_rdFIFO_wrusedw >= burst_len) begin
        rdchannel <= 3'h4;
    end
    else if(fsm_cs == FSM_ARBIT && ch5_rd_en && 9'd256 - ch5_rdFIFO_wrusedw >= burst_len) begin
        rdchannel <= 3'h5;
    end
    else if(fsm_cs == FSM_ARBIT && ch6_rd_en && 9'd256 - ch6_rdFIFO_wrusedw >= burst_len) begin
        rdchannel <= 3'h6;
    end
    else if(fsm_cs == FSM_ARBIT && ch7_rd_en && 9'd256 - ch7_rdFIFO_wrusedw >= burst_len) begin
        rdchannel <= 3'h7;
    end
end
//==========================================================================
//==    完成一次行突发后,写行的计数递增
//==========================================================================
//写通道0
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch0_wr_vcnt <= 16'h0;
    end
    else if((wrchannel == 3'h0 && fsm_cs == FSM_WRITE && burst_wrdone && ch0_wr_vcnt == ch0_height - 16'h1) || ch0_wr_rst) begin
        ch0_wr_vcnt <= 16'h0;
    end
    else if(wrchannel == 3'h0 && fsm_cs == FSM_WRITE && burst_wrdone) begin
        ch0_wr_vcnt <= ch0_wr_vcnt + 16'h1;
    end
end

//写通道1
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch1_wr_vcnt <= 16'h0;
    end
    else if((wrchannel == 3'h1 && fsm_cs == FSM_WRITE && burst_wrdone && ch1_wr_vcnt == ch1_height - 16'h1) || ch1_wr_rst) begin
        ch1_wr_vcnt <= 16'h0;
    end
    else if(wrchannel == 3'h1 && fsm_cs == FSM_WRITE && burst_wrdone) begin
        ch1_wr_vcnt <= ch1_wr_vcnt + 16'h1;
    end
end

//写通道2
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch2_wr_vcnt <= 16'h0;
    end
    else if((wrchannel == 3'h2 && fsm_cs == FSM_WRITE && burst_wrdone && ch2_wr_vcnt == ch2_height - 16'h1) || ch2_wr_rst) begin
        ch2_wr_vcnt <= 16'h0;
    end
    else if(wrchannel == 3'h2 && fsm_cs == FSM_WRITE && burst_wrdone) begin
        ch2_wr_vcnt <= ch2_wr_vcnt + 16'h1;
    end
end

//写通道3
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch3_wr_vcnt <= 16'h0;
    end
    else if((wrchannel == 3'h3 && fsm_cs == FSM_WRITE && burst_wrdone && ch3_wr_vcnt == ch3_height - 16'h1) || ch3_wr_rst) begin
        ch3_wr_vcnt <= 16'h0;
    end
    else if(wrchannel == 3'h3 && fsm_cs == FSM_WRITE && burst_wrdone) begin
        ch3_wr_vcnt <= ch3_wr_vcnt + 16'h1;
    end
end

//写通道4
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch4_wr_vcnt <= 16'h0;
    end
    else if((wrchannel == 3'h4 && fsm_cs == FSM_WRITE && burst_wrdone && ch4_wr_vcnt == ch4_height - 16'h1) || ch4_wr_rst) begin
        ch4_wr_vcnt <= 16'h0;
    end
    else if(wrchannel == 3'h4 && fsm_cs == FSM_WRITE && burst_wrdone) begin
        ch4_wr_vcnt <= ch4_wr_vcnt + 16'h1;
    end
end

//写通道5
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch5_wr_vcnt <= 16'h0;
    end
    else if((wrchannel == 3'h5 && fsm_cs == FSM_WRITE && burst_wrdone && ch5_wr_vcnt == ch5_height - 16'h1) || ch5_wr_rst) begin
        ch5_wr_vcnt <= 16'h0;
    end
    else if(wrchannel == 3'h5 && fsm_cs == FSM_WRITE && burst_wrdone) begin
        ch5_wr_vcnt <= ch5_wr_vcnt + 16'h1;
    end
end

//写通道6
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch6_wr_vcnt <= 16'h0;
    end
    else if((wrchannel == 3'h6 && fsm_cs == FSM_WRITE && burst_wrdone && ch6_wr_vcnt == ch6_height - 16'h1) || ch6_wr_rst) begin
        ch6_wr_vcnt <= 16'h0;
    end
    else if(wrchannel == 3'h6 && fsm_cs == FSM_WRITE && burst_wrdone) begin
        ch6_wr_vcnt <= ch6_wr_vcnt + 16'h1;
    end
end

//写通道7
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch7_wr_vcnt <= 16'h0;
    end
    else if((wrchannel == 3'h7 && fsm_cs == FSM_WRITE && burst_wrdone && ch7_wr_vcnt == ch7_height - 16'h1) || ch7_wr_rst) begin
        ch7_wr_vcnt <= 16'h0;
    end
    else if(wrchannel == 3'h7 && fsm_cs == FSM_WRITE && burst_wrdone) begin
        ch7_wr_vcnt <= ch7_wr_vcnt + 16'h1;
    end
end
//==========================================================================
//==    完成一次行突发后,读行的计数递增
//==========================================================================
//读通道0
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch0_rd_vcnt <= 16'h0;
    end
    else if((rdchannel == 3'h0 && fsm_cs == FSM_READ && burst_rddone && ch0_rd_vcnt == ch0_height - 16'h1) || ch0_rd_rst) begin
        ch0_rd_vcnt <= 16'h0;
    end
    else if(rdchannel == 3'h0 && fsm_cs == FSM_READ && burst_rddone) begin
        ch0_rd_vcnt <= ch0_rd_vcnt + 16'h1;
    end
end

//读通道1
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch1_rd_vcnt <= 16'h0;
    end
    else if((rdchannel == 3'h1 && fsm_cs == FSM_READ && burst_rddone && ch1_rd_vcnt == ch1_height - 16'h1) || ch1_rd_rst) begin
        ch1_rd_vcnt <= 16'h0;
    end
    else if(rdchannel == 3'h1 && fsm_cs == FSM_READ && burst_rddone) begin
        ch1_rd_vcnt <= ch1_rd_vcnt + 16'h1;
    end
end

//读通道2
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch2_rd_vcnt <= 16'h0;
    end
    else if((rdchannel == 3'h2 && fsm_cs == FSM_READ && burst_rddone && ch2_rd_vcnt == ch2_height - 16'h1) || ch2_rd_rst) begin
        ch2_rd_vcnt <= 16'h0;
    end
    else if(rdchannel == 3'h2 && fsm_cs == FSM_READ && burst_rddone) begin
        ch2_rd_vcnt <= ch2_rd_vcnt + 16'h1;
    end
end

//读通道3
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch3_rd_vcnt <= 16'h0;
    end
    else if((rdchannel == 3'h3 && fsm_cs == FSM_READ && burst_rddone && ch3_rd_vcnt == ch3_height - 16'h1) || ch3_rd_rst) begin
        ch3_rd_vcnt <= 16'h0;
    end
    else if(rdchannel == 3'h3 && fsm_cs == FSM_READ && burst_rddone) begin
        ch3_rd_vcnt <= ch3_rd_vcnt + 16'h1;
    end
end

//读通道4
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch4_rd_vcnt <= 16'h0;
    end
    else if((rdchannel == 3'h4 && fsm_cs == FSM_READ && burst_rddone && ch4_rd_vcnt == ch4_height - 16'h1) || ch4_rd_rst) begin
        ch4_rd_vcnt <= 16'h0;
    end
    else if(rdchannel == 3'h4 && fsm_cs == FSM_READ && burst_rddone) begin
        ch4_rd_vcnt <= ch4_rd_vcnt + 16'h1;
    end
end

//读通道5
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch5_rd_vcnt <= 16'h0;
    end
    else if((rdchannel == 3'h5 && fsm_cs == FSM_READ && burst_rddone && ch5_rd_vcnt == ch5_height - 16'h1) || ch5_rd_rst) begin
        ch5_rd_vcnt <= 16'h0;
    end
    else if(rdchannel == 3'h5 && fsm_cs == FSM_READ && burst_rddone) begin
        ch5_rd_vcnt <= ch5_rd_vcnt + 16'h1;
    end
end

//读通道6
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch6_rd_vcnt <= 16'h0;
    end
    else if((rdchannel == 3'h6 && fsm_cs == FSM_READ && burst_rddone && ch6_rd_vcnt == ch6_height - 16'h1) || ch6_rd_rst) begin
        ch6_rd_vcnt <= 16'h0;
    end
    else if(rdchannel == 3'h6 && fsm_cs == FSM_READ && burst_rddone) begin
        ch6_rd_vcnt <= ch6_rd_vcnt + 16'h1;
    end
end

//读通道7
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch7_rd_vcnt <= 16'h0;
    end
    else if((rdchannel == 3'h7 && fsm_cs == FSM_READ && burst_rddone && ch7_rd_vcnt == ch7_height - 16'h1) || ch7_rd_rst) begin
        ch7_rd_vcnt <= 16'h0;
    end
    else if(rdchannel == 3'h7 && fsm_cs == FSM_READ && burst_rddone) begin
        ch7_rd_vcnt <= ch7_rd_vcnt + 16'h1;
    end
end
//==========================================================================
//==    读写地址设计
//==========================================================================
//写地址:逐行,列[9:0],行[9:0]
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        burst_wraddr <= `LOCAL_ADDR_W'h0;
    end
    else if(wrchannel == 3'h0) begin
        burst_wraddr <= {ch0_wraddr_msb,ch0_addr,20'h0} + {ch0_wr_vcnt[9:0],10'h0};
    end
    else if(wrchannel == 3'h1) begin
        burst_wraddr <= {ch1_wraddr_msb,ch1_addr,20'h0} + {ch1_wr_vcnt[9:0],10'h0};
    end
    else if(wrchannel == 3'h2) begin
        burst_wraddr <= {ch2_wraddr_msb,ch2_addr,20'h0} + {ch2_wr_vcnt[9:0],10'h0};
    end
    else if(wrchannel == 3'h3) begin
        burst_wraddr <= {ch3_wraddr_msb,ch3_addr,20'h0} + {ch3_wr_vcnt[9:0],10'h0};
    end
    else if(wrchannel == 3'h4) begin
        burst_wraddr <= {ch4_wraddr_msb,ch4_addr,20'h0} + {ch4_wr_vcnt[9:0],10'h0};
    end
    else if(wrchannel == 3'h5) begin
        burst_wraddr <= {ch5_wraddr_msb,ch5_addr,20'h0} + {ch5_wr_vcnt[9:0],10'h0};
    end
    else if(wrchannel == 3'h6) begin
        burst_wraddr <= {ch6_wraddr_msb,ch6_addr,20'h0} + {ch6_wr_vcnt[9:0],10'h0};
    end
    else if(wrchannel == 3'h7) begin
        burst_wraddr <= {ch7_wraddr_msb,ch7_addr,20'h0} + {ch7_wr_vcnt[9:0],10'h0};
    end
end

//读地址:逐行,列[9:0],行[9:0]
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        burst_rdaddr <= `LOCAL_ADDR_W'h0;
    end
    else if(rdchannel == 3'h0) begin
        burst_rdaddr <= {ch0_rdaddr_msb,ch0_addr,20'h0} + {ch0_rd_vcnt[9:0],10'h0};
    end
    else if(rdchannel == 3'h1) begin
        burst_rdaddr <= {ch1_rdaddr_msb,ch1_addr,20'h0} + {ch1_rd_vcnt[9:0],10'h0};
    end
    else if(rdchannel == 3'h2) begin
        burst_rdaddr <= {ch2_rdaddr_msb,ch2_addr,20'h0} + {ch2_rd_vcnt[9:0],10'h0};
    end
    else if(rdchannel == 3'h3) begin
        burst_rdaddr <= {ch3_rdaddr_msb,ch3_addr,20'h0} + {ch3_rd_vcnt[9:0],10'h0};
    end
    else if(rdchannel == 3'h4) begin
        burst_rdaddr <= {ch4_rdaddr_msb,ch4_addr,20'h0} + {ch4_rd_vcnt[9:0],10'h0};
    end
    else if(rdchannel == 3'h5) begin
        burst_rdaddr <= {ch5_rdaddr_msb,ch5_addr,20'h0} + {ch5_rd_vcnt[9:0],10'h0};
    end
    else if(rdchannel == 3'h6) begin
        burst_rdaddr <= {ch6_rdaddr_msb,ch6_addr,20'h0} + {ch6_rd_vcnt[9:0],10'h0};
    end
    else if(rdchannel == 3'h7) begin
        burst_rdaddr <= {ch7_rdaddr_msb,ch7_addr,20'h0} + {ch7_rd_vcnt[9:0],10'h0};
    end
end
//==========================================================================
//==    读写请求
//==========================================================================
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        burst_wrreq <= 1'h0;
    end
    else if(burst_wrreq == 1'h0 && fsm_cs == FSM_WRITE) begin
        burst_wrreq <= 1'b1;
    end
    else if(burst_wrreq == 1'h1 && fsm_cs == FSM_WRITE && burst_wrdone) begin
        burst_wrreq <= 1'b0;
    end
end

always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        burst_rdreq <= 1'h0;
    end
    else if(burst_rdreq == 1'h0 && fsm_cs == FSM_READ) begin
        burst_rdreq <= 1'b1;
    end
    else if(burst_rdreq == 1'h1 && fsm_cs == FSM_READ && burst_rddone) begin
        burst_rdreq <= 1'b0;
    end
end
//==========================================================================
//==    乒乓操作,写完一帧图像乒乓操作切换分区
//==========================================================================
//读写通道0
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch0_wraddr_msb <= 2'h1;
    end
    else if(wrchannel == 3'h0 && burst_wrdone && ch0_wr_vcnt == ch0_height - 16'h1 && ch0_rdaddr_msb != ch0_wraddr_msb + 2'h1) begin
        ch0_wraddr_msb <= ch0_wraddr_msb + 2'h1;
    end
end

always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch0_rdaddr_msb <= 2'h0;
    end
    else if(rdchannel == 3'h0 && burst_rddone && ch0_rd_vcnt == ch0_height - 16'h1 && ch0_wraddr_msb != ch0_rdaddr_msb + 2'h1) begin
        ch0_rdaddr_msb <= ch0_rdaddr_msb + 2'h1;
    end
end

//读写通道1
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch1_wraddr_msb <= 2'h1;
    end
    else if(wrchannel == 3'h1 && burst_wrdone && ch1_wr_vcnt == ch1_height - 16'h1 && ch1_rdaddr_msb != ch1_wraddr_msb + 2'h1) begin
        ch1_wraddr_msb <= ch1_wraddr_msb + 2'h1;
    end
end

always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch1_rdaddr_msb <= 2'h0;
    end
    else if(rdchannel == 3'h1 && burst_rddone && ch1_rd_vcnt == ch1_height - 16'h1 && ch1_wraddr_msb != ch1_rdaddr_msb + 2'h1) begin
        ch1_rdaddr_msb <= ch1_rdaddr_msb + 2'h1;
    end
end

//读写通道2
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch2_wraddr_msb <= 2'h1;
    end
    else if(wrchannel == 3'h2 && burst_wrdone && ch2_wr_vcnt == ch2_height - 16'h1 && ch2_rdaddr_msb != ch2_wraddr_msb + 2'h1) begin
        ch2_wraddr_msb <= ch2_wraddr_msb + 2'h1;
    end
end

always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch2_rdaddr_msb <= 2'h0;
    end
    else if(rdchannel == 3'h2 && burst_rddone && ch2_rd_vcnt == ch2_height - 16'h1 && ch2_wraddr_msb != ch2_rdaddr_msb + 2'h1) begin
        ch2_rdaddr_msb <= ch2_rdaddr_msb + 2'h1;
    end
end

//读写通道3
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch3_wraddr_msb <= 2'h1;
    end
    else if(wrchannel == 3'h3 && burst_wrdone && ch3_wr_vcnt == ch3_height - 16'h1 && ch3_rdaddr_msb != ch3_wraddr_msb + 2'h1) begin
        ch3_wraddr_msb <= ch3_wraddr_msb + 2'h1;
    end
end

always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch3_rdaddr_msb <= 2'h0;
    end
    else if(rdchannel == 3'h3 && burst_rddone && ch3_rd_vcnt == ch3_height - 16'h1 && ch3_wraddr_msb != ch3_rdaddr_msb + 2'h1) begin
        ch3_rdaddr_msb <= ch3_rdaddr_msb + 2'h1;
    end
end

//读写通道4
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch4_wraddr_msb <= 2'h1;
    end
    else if(wrchannel == 3'h4 && burst_wrdone && ch4_wr_vcnt == ch4_height - 16'h1 && ch4_rdaddr_msb != ch4_wraddr_msb + 2'h1) begin
        ch4_wraddr_msb <= ch4_wraddr_msb + 2'h1;
    end
end

always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch4_rdaddr_msb <= 2'h0;
    end
    else if(rdchannel == 3'h4 && burst_rddone && ch4_rd_vcnt == ch4_height - 16'h1 && ch4_wraddr_msb != ch4_rdaddr_msb + 2'h1) begin
        ch4_rdaddr_msb <= ch4_rdaddr_msb + 2'h1;
    end
end

//读写通道5
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch5_wraddr_msb <= 2'h1;
    end
    else if(wrchannel == 3'h5 && burst_wrdone && ch5_wr_vcnt == ch5_height - 16'h1 && ch5_rdaddr_msb != ch5_wraddr_msb + 2'h1) begin
        ch5_wraddr_msb <= ch5_wraddr_msb + 2'h1;
    end
end

always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch5_rdaddr_msb <= 2'h0;
    end
    else if(rdchannel == 3'h5 && burst_rddone && ch5_rd_vcnt == ch5_height - 16'h1 && ch5_wraddr_msb != ch5_rdaddr_msb + 2'h1) begin
        ch5_rdaddr_msb <= ch5_rdaddr_msb + 2'h1;
    end
end

//读写通道6
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch6_wraddr_msb <= 2'h1;
    end
    else if(wrchannel == 3'h6 && burst_wrdone && ch6_wr_vcnt == ch6_height - 16'h1 && ch6_rdaddr_msb != ch6_wraddr_msb + 2'h1) begin
        ch6_wraddr_msb <= ch6_wraddr_msb + 2'h1;
    end
end

always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch6_rdaddr_msb <= 2'h0;
    end
    else if(rdchannel == 3'h6 && burst_rddone && ch6_rd_vcnt == ch6_height - 16'h1 && ch6_wraddr_msb != ch6_rdaddr_msb + 2'h1) begin
        ch6_rdaddr_msb <= ch6_rdaddr_msb + 2'h1;
    end
end

//读写通道7
//---------------------------------------------------
always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch7_wraddr_msb <= 2'h1;
    end
    else if(wrchannel == 3'h7 && burst_wrdone && ch7_wr_vcnt == ch7_height - 16'h1 && ch7_rdaddr_msb != ch7_wraddr_msb + 2'h1) begin
        ch7_wraddr_msb <= ch7_wraddr_msb + 2'h1;
    end
end

always @ (posedge phy_clk or negedge rst_n) begin
    if(!rst_n) begin
        ch7_rdaddr_msb <= 2'h0;
    end
    else if(rdchannel == 3'h7 && burst_rddone && ch7_rd_vcnt == ch7_height - 16'h1 && ch7_wraddr_msb != ch7_rdaddr_msb + 2'h1) begin
        ch7_rdaddr_msb <= ch7_rdaddr_msb + 2'h1;
    end
end



endmodule

(3) DDR2_burst

DDR2_burst
//**************************************************************************
// *** 名称 : DDR2_burst.v
// *** 作者 : xianyu_FPGA
// *** 博客 : https://www.cnblogs.com/xianyufpga/
// *** 日期 : 2020年6月
// *** 描述 : 完成一次DDR2的突发读写
//**************************************************************************

module DDR2_burst
//============================< 参数 >======================================
#(
parameter MEM_DM_W              = 4                     ,   //DDR2 dm位宽
parameter MEM_DQS_W             = 4                     ,   //DDR2 dqs位宽
parameter MEM_BANK_W            = 3                     ,   //DDR2 bank位宽
parameter MEM_ADDR_W            = 13                    ,   //DDR2 地址位宽
parameter MEM_DQ_W              = 32                    ,   //DDR2 数据位宽,一片16两片32
//-------------------------------------------------------
parameter LOCAL_SIZE_W          = 3                     ,   //DDR2 IP核local_size位宽
parameter LOCAL_DATA_W          = 64                    ,   //DDR2 IP核数据位宽
parameter LOCAL_ADDR_W          = 25                        //DDR2 IP核地址位宽
)
//============================< 端口 >======================================
(
//DDR2 IP核接口 -----------------------------------------
input                           pll_ref_clk             ,   //DDR2 参考时钟
input                           global_reset_n          ,   //FPGA 全局复位
output                          phy_clk                 ,   //DDR2 工作时钟
output                          DDR2_rst_n              ,   //DDR2 同步复位
//突发读写接口 ------------------------------------------
input                           burst_rd_req            ,   //突发读请求
input                           burst_wr_req            ,   //突发写请求
input   [LOCAL_ADDR_W -3:0]     burst_rd_len            ,   //突发读长度
input   [LOCAL_ADDR_W -3:0]     burst_wr_len            ,   //突发写长度
input   [LOCAL_ADDR_W -1:0]     burst_rd_addr           ,   //突发读地址
input   [LOCAL_ADDR_W -1:0]     burst_wr_addr           ,   //突发写地址
output  [LOCAL_DATA_W -1:0]     burst_rd_data           ,   //突发读数据
input   [LOCAL_DATA_W -1:0]     burst_wr_data           ,   //突发写数据
output                          burst_rd_ack            ,   //突发读应答,连接FIFO
output                          burst_wr_ack            ,   //突发写应答,连接FIFO
output  reg                     burst_rd_done           ,   //突发读完成信号
output  reg                     burst_wr_done           ,   //突发写完成信号
//DDR2 芯片接口 -----------------------------------------
output                          mem_odt                 ,   //DDR2 片上终结信号
output                          mem_cs_n                ,   //DDR2 片选信号
output                          mem_cke                 ,   //DDR2 时钟使能信号
output  [MEM_ADDR_W   -1:0]     mem_addr                ,   //DDR2 地址总线
output  [MEM_BANK_W   -1:0]     mem_ba                  ,   //DDR2 BANK信号
output                          mem_ras_n               ,   //DDR2 行地址选择信号
output                          mem_cas_n               ,   //DDR2 列地址选择信号
output                          mem_we_n                ,   //DDR2 写使能信号
output  [MEM_DM_W     -1:0]     mem_dm                  ,   //DDR2 数据掩膜信号
inout                           mem_clk                 ,   //DDR2 时钟信号
inout                           mem_clk_n               ,   //DDR2 时钟反相信号
inout   [MEM_DQ_W     -1:0]     mem_dq                  ,   //DDR2 数据总线
inout   [MEM_DQS_W    -1:0]     mem_dqs                     //DDR2 数据源同步信号
);
//============================< 信号 >======================================
reg     [LOCAL_ADDR_W -1:0]     local_address           ;   //DDR2 IP核地址总线
wire                            local_write_req         ;   //DDR2 IP核写请求信号
wire                            local_read_req          ;   //DDR2 IP核读请求信号
wire                            local_burstbegin        ;   //DDR2 IP核突发起始信号
wire    [LOCAL_DATA_W -1:0]     local_wdata             ;   //DDR2 IP核写数据总线
reg     [LOCAL_SIZE_W -1:0]     local_size              ;   //DDR2 IP核突发大小
wire                            local_ready             ;   //DDR2 IP核准备好信号
wire    [LOCAL_DATA_W -1:0]     local_rdata             ;   //DDR2 IP核读数据总线
wire                            local_rdata_valid       ;   //DDR2 IP核读数据有效信号
wire                            reset_phy_clk_n         ;   //DDR2 IP核复位后同步信号
wire                            local_init_done         ;   //DDR2 IP核初始化完成信号
//-------------------------------------------------------
reg     [4:0]                   state                   ;   //状态机
reg     [LOCAL_ADDR_W -1:0]     wr_len                  ;   //读突发长度
reg     [LOCAL_ADDR_W -1:0]     rd_len                  ;   //写突发长度
reg     [LOCAL_ADDR_W -1:0]     wr_addr_cnt             ;   //写地址计数器
reg     [LOCAL_ADDR_W -1:0]     wr_burst_cnt            ;   //一次突发写内的数据计数
reg     [LOCAL_ADDR_W -1:0]     rd_addr_cnt             ;   //读地址计数器
reg     [LOCAL_ADDR_W -1:0]     rd_data_cnt             ;   //读数据计数器
//============================< 参数 >======================================
localparam   WR_SIZE            = 2                     ;   //总线写突发
localparam   RD_SIZE            = 2                     ;   //总线读突发
//------------------------------------------------------
localparam   IDLE               = 5'b00001              ;   //空闲状态
localparam   ARBIT              = 5'b00010              ;   //仲裁状态
localparam   WR                 = 5'b00100              ;   //写状态
localparam   RD_ADDR            = 5'b01000              ;   //读状态
localparam   RD_WAIT            = 5'b10000              ;   //读等待状态
//==========================================================================
//==    DDR2 IP核,PLL 100Mhz,DDR2 166.7Mhz,Full Rate
//==========================================================================
DDR2 u_DDR2
(
    .pll_ref_clk                (pll_ref_clk            ),  //DDR2 参考时钟
    .global_reset_n             (global_reset_n         ),  //全局复位信号
    .soft_reset_n               (1'b1                   ),  //软复位信号
    .local_address              (local_address          ),  //DDR2 IP核地址总线
    .local_write_req            (local_write_req        ),  //DDR2 IP核写请求信号
    .local_read_req             (local_read_req         ),  //DDR2 IP核读请求信号
    .local_burstbegin           (local_burstbegin       ),  //DDR2 IP核突发起始信号
    .local_wdata                (local_wdata            ),  //DDR2 IP核写数据总线
    .local_be                   (8'b1111_1111           ),  //DDR2 IP核字节使能信号
    .local_size                 (local_size             ),  //DDR2 IP核突发大小
    .local_ready                (local_ready            ),  //DDR2 IP核准备好信号
    .local_rdata                (local_rdata            ),  //DDR2 IP核读数据总线
    .local_rdata_valid          (local_rdata_valid      ),  //DDR2 IP核读数据有效信号
    .local_refresh_ack          (                       ),  //DDR2 IP核自刷新应答信号
    .local_init_done            (local_init_done        ),  //DDR2 IP核初始化完成信号
    //---------------------------------------------------
    .mem_odt                    (mem_odt                ),  //DDR2片上终结信号
    .mem_cs_n                   (mem_cs_n               ),  //DDR2片选信号
    .mem_cke                    (mem_cke                ),  //DDR2时钟使能信号
    .mem_addr                   (mem_addr               ),  //DDR2地址总线
    .mem_ba                     (mem_ba                 ),  //DDR2组地址信号
    .mem_ras_n                  (mem_ras_n              ),  //DDR2行地址选择信
    .mem_cas_n                  (mem_cas_n              ),  //DDR2列地址选择信
    .mem_we_n                   (mem_we_n               ),  //DDR2写使能信号
    .mem_dm                     (mem_dm                 ),  //DDR2数据掩膜信号
    .mem_clk                    (mem_clk                ),  //DDR2时钟信号
    .mem_clk_n                  (mem_clk_n              ),  //DDR2时钟反相信号
    .mem_dq                     (mem_dq                 ),  //DDR2数据总线
    .mem_dqs                    (mem_dqs                ),  //DDR2数据源同步信号
    .phy_clk                    (phy_clk                ),  //DDR2 IP核工作时钟
    .reset_phy_clk_n            (reset_phy_clk_n        ),  //DDR2 IP核同步后的复位信号
    .reset_request_n            (                       ),  //DDR2 IP核复位请求信号
    .aux_full_rate_clk          (                       ),  //DDR2 IP核全速率时钟
    .aux_half_rate_clk          (                       )   //DDR2 IP核半速率时钟
);

//本模块复位信号
assign DDR2_rst_n = reset_phy_clk_n & local_init_done;
//==========================================================================
//==    状态机
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        state <= IDLE;
        burst_wr_done <= 1'b0;
        burst_rd_done <= 1'b0;
    end
    else begin
        case(state)
            IDLE:   begin
                        burst_wr_done <= 1'b0;
                        burst_rd_done <= 1'b0;
                        state <= ARBIT;
                    end
            ARBIT:  begin
                        if(burst_wr_req) begin
                            state <= WR;
                        end
                        else if(burst_rd_req) begin
                            state <= RD_ADDR;
                        end
                    end
            WR:     begin
                        if(wr_addr_cnt + wr_burst_cnt >= wr_len - 1 && local_ready) begin
                            state <= IDLE;
                            burst_wr_done <= 1'b1;
                        end
                    end
            RD_ADDR:begin
                        if(rd_addr_cnt >= rd_len - RD_SIZE && local_ready) begin
                            state <= RD_WAIT;
                        end
                    end
            RD_WAIT:begin
                        if(rd_data_cnt >= rd_len - 1) begin
                            state <= IDLE;
                            burst_rd_done <= 1'b1;
                        end
                    end
            default:
                        state <= IDLE;
        endcase
    end
end
//------------------------------------------ 状态机名称,测试用
reg [55:0] state_name; //1个字符8位宽
always @(*) begin
    case(state)
        IDLE    :   state_name = "IDLE";
        ARBIT   :   state_name = "ARBIT";
        WR      :   state_name = "WR";
        RD_ADDR :   state_name = "RD_ADDR";
        RD_WAIT :   state_name = "RD_WAIT";
        default :   state_name = "IDLE";
    endcase
end
//==========================================================================
//==    在进入读状态前锁存读突发长度
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        wr_len <= 'h0;
    end
    else if(state == ARBIT && burst_wr_req) begin
        wr_len <= burst_wr_len;
    end
end

always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        rd_len <= 'h0;
    end
    else if(state == ARBIT && burst_rd_req) begin
        rd_len <= burst_rd_len;
    end
end
//==========================================================================
//==    写突发的数据计数:0101010101
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        wr_burst_cnt <= 'h0;
    end
    else if(state == WR && local_ready) begin
        if(wr_burst_cnt >= WR_SIZE - 1)
            wr_burst_cnt <= 'h0;
        else
            wr_burst_cnt <= wr_burst_cnt + 'h1;
    end
end
//==========================================================================
//==    每凑齐2个数据则地址+2
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        wr_addr_cnt <= 'h0;
    end
    else if(state == WR && local_ready) begin
        if(wr_addr_cnt + wr_burst_cnt >= wr_len - 1)
            wr_addr_cnt <= 'h0;
        else if(wr_burst_cnt >= WR_SIZE - 1)
            wr_addr_cnt <= wr_addr_cnt + WR_SIZE;    
    end
end
//==========================================================================
//==    每给出读指令时读地址+2
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        rd_addr_cnt <= 'h0;
    end
    else if(state == RD_ADDR && local_ready) begin
        if(rd_addr_cnt >= rd_len - RD_SIZE)
            rd_addr_cnt <= 'h0;
        else
            rd_addr_cnt <= rd_addr_cnt + RD_SIZE;
    end
end
//==========================================================================
//==    每读出一个数据地址递+1
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        rd_data_cnt <= 'h0;
    end
    else if(local_rdata_valid) begin
        if(rd_data_cnt >= rd_len - 1)
            rd_data_cnt <= 'h0;
        else
            rd_data_cnt <= rd_data_cnt + 'h1;
    end
end
//==========================================================================
//==    锁存local_size并在最后一次读写时如果不足突发大小则更改local_size为不足的大小
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        local_size <= 'h0;
    end
    else if(state == ARBIT && burst_wr_req) begin
        local_size <= (burst_wr_len >= WR_SIZE) ? WR_SIZE : burst_wr_len;
    end
    else if(state == ARBIT && burst_rd_req) begin
        local_size <= (burst_rd_len >= RD_SIZE) ? RD_SIZE : burst_rd_len;
    end
    else if(state == WR && wr_burst_cnt == WR_SIZE - 1 && wr_addr_cnt + {WR_SIZE,1'b0} > wr_len && local_ready) begin
        local_size <= wr_len - wr_addr_cnt - WR_SIZE;
    end
    else if(state == RD_ADDR && rd_addr_cnt + {RD_SIZE,1'b0} > rd_len && local_ready) begin
        local_size <= rd_len - rd_addr_cnt - RD_SIZE;
    end
end
//==========================================================================
//==    锁存local_address,并且在完成一次突发读写时递增读写地址
//==========================================================================
always @ (posedge phy_clk or negedge DDR2_rst_n) begin
    if(!DDR2_rst_n) begin
        local_address <= 'h0;
    end
    else if(state == ARBIT && burst_wr_req) begin
        local_address <= burst_wr_addr;
    end
    else if(state == ARBIT && burst_rd_req) begin
        local_address <= burst_rd_addr;
    end
    else if(state == WR && (wr_burst_cnt == WR_SIZE - 1) && local_ready) begin
        local_address <= local_address + WR_SIZE;
    end
    else if(state == RD_ADDR && local_ready) begin
        local_address <= local_address + RD_SIZE;
    end
end
//==========================================================================
//==    其他信号
//==========================================================================
//burstbegin信号,随便怎么写都行,直接赋值1'b1也能跑
assign local_burstbegin = (state == WR || state == RD_ADDR) ? 1'b1 : 1'b0;

//写数据
assign local_wdata = burst_wr_data;

//写应答,即写FIFO的读使能
assign burst_wr_ack = (state == WR && local_ready) ? 1'b1 : 1'b0;

//读数据
assign burst_rd_data = local_rdata;

//读应答,即读FIFO的写使能
assign burst_rd_ack = local_rdata_valid;

//写请求
assign local_write_req = (state == WR) ? 1'b1 : 1'b0;

//读请求
assign local_read_req = (state == RD_ADDR) ? 1'b1 : 1'b0;



endmodule

(4) DDR2_param

DDR2_param
//**************************************************************************
// *** 名称 : DDR2_param.v
// *** 作者 : xianyu_FPGA
// *** 博客 : https://www.cnblogs.com/xianyufpga/
// *** 日期 : 2020年6月
// *** 描述 : DDR2参数,PLL 100Mhz,DDR2 166.7Mhz,Full Rate
//**************************************************************************
`define     MEM_ADDR_W          13      //DDR2 地址位宽
`define     MEM_BANK_W          3       //DDR2 bank位宽
`define     MEM_DM_W            4       //DDR2 dm位宽
`define     MEM_DQ_W            32      //DDR2 数据位宽,一片16两片32
`define     MEM_DQS_W           4       //DDR2 DQS位宽

`define     LOCAL_DATA_W        64      //DDR2 IP核全速率数据位宽
`define     LOCAL_ADDR_W        25      //DDR2 IP核全速率地址位宽
`define     LOCAL_SIZE_W        3       //DDR2 IP核全速率local_size位宽
`define     LOCAL_BE_W          8       //DDR2 IP核全速率local_be位宽

`define     BURST_W             16      //burst长度位宽,burst_len + BURST_SIZE

3、VGA_driver

VGA_driver
//**************************************************************************
// *** 名称 : VGA_driver.v
// *** 作者 : xianyu_FPGA
// *** 博客 : https://www.cnblogs.com/xianyufpga/
// *** 日期 : 2019-06-26
// *** 描述 : VGA驱动模块
//**************************************************************************

module VGA_driver
//========================< 参数 >==========================================
//                    640x480 @60Hz 25Mhz
#(
parameter H_TOTAL           = 800                               ,   //行扫描周期
parameter H_ADDR            = 640                               ,   //行有效数据   
parameter H_SYNC            = 96                                ,   //行同步  
parameter H_BACK            = 48                                ,   //行显示后沿
parameter V_TOTAL           = 525                               ,   //场扫描周期
parameter V_ADDR            = 480                               ,   //场有效数据   
parameter V_SYNC            = 2                                 ,   //场同步   
parameter V_BACK            = 33                                    //场显示后沿
)
//========================< 端口 >==========================================
(
//system --------------------------------------------------------
input   wire                clk                                 ,   //时钟
input   wire                rst_n                               ,   //复位,低电平有效
//VGA_display ---------------------------------------------------
output  wire                ch0_VGA_req                         ,   //请求图像数据
output  wire                ch1_VGA_req                         ,   //请求图像数据
output  wire                ch2_VGA_req                         ,   //请求图像数据
output  wire                ch3_VGA_req                         ,   //请求图像数据
output  wire                ch4_VGA_req                         ,   //请求图像数据
output  wire                ch5_VGA_req                         ,   //请求图像数据
output  wire                ch6_VGA_req                         ,   //请求图像数据
output  wire                ch7_VGA_req                         ,   //请求图像数据
input   wire  [15:0]        ch0_VGA_din                         ,   //得到图像数据
input   wire  [15:0]        ch1_VGA_din                         ,   //得到图像数据
input   wire  [15:0]        ch2_VGA_din                         ,   //得到图像数据
input   wire  [15:0]        ch3_VGA_din                         ,   //得到图像数据
input   wire  [15:0]        ch4_VGA_din                         ,   //得到图像数据
input   wire  [15:0]        ch5_VGA_din                         ,   //得到图像数据
input   wire  [15:0]        ch6_VGA_din                         ,   //得到图像数据
input   wire  [15:0]        ch7_VGA_din                         ,   //得到图像数据
//VGA output ----------------------------------------------------
output  wire                VGA_clk                             ,   //VGA接口时钟信号
output  wire                VGA_hsync                           ,   //VGA接口行信号
output  wire                VGA_vsync                           ,   //VGA接口场信号
output  wire  [15:0]        VGA_data                                //VGA接口数据信号
);
//========================< 颜色 >==========================================
localparam BLACK            = 16'h0000                          ;   //黑
localparam WHITE            = 16'hffff                          ;   //白
localparam RED              = 16'hf800                          ;   //红
localparam ORANGE           = 16'hfd60                          ;   //橙
localparam YELLOW           = 16'hffe0                          ;   //黄
localparam GREEN            = 16'h07e0                          ;   //绿
localparam CYAN             = 16'h07ff                          ;   //青
localparam BLUE             = 16'h001f                          ;   //蓝
localparam PURPLE           = 16'h801f                          ;   //紫
//========================< 信号 >==========================================
reg   [15:0]                cnt_h                               ;
wire                        add_cnt_h                           ;
wire                        end_cnt_h                           ;
reg   [15:0]                cnt_v                               ;
wire                        add_cnt_v                           ;
wire                        end_cnt_v                           ;
//---------------------------------------------------------------
reg                         ch0_VGA_de_r1                       ;
reg                         ch1_VGA_de_r1                       ;
reg                         ch2_VGA_de_r1                       ;
reg                         ch3_VGA_de_r1                       ;
reg                         ch4_VGA_de_r1                       ;
reg                         ch5_VGA_de_r1                       ;
reg                         ch6_VGA_de_r1                       ;
reg                         ch7_VGA_de_r1                       ;
reg                         ch0_VGA_de_r2                       ;
reg                         ch1_VGA_de_r2                       ;
reg                         ch2_VGA_de_r2                       ;
reg                         ch3_VGA_de_r2                       ;
reg                         ch4_VGA_de_r2                       ;
reg                         ch5_VGA_de_r2                       ;
reg                         ch6_VGA_de_r2                       ;
reg                         ch7_VGA_de_r2                       ;
//==========================================================================
//==    行、场计数
//==========================================================================
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        cnt_h <= 0;
    else if(add_cnt_h) begin
        if(end_cnt_h)
            cnt_h <= 0;
        else
            cnt_h <= cnt_h + 1;
    end
end

assign add_cnt_h = 1;
assign end_cnt_h = add_cnt_h && cnt_h==H_TOTAL-1;

always @(posedge clk or negedge rst_n) begin 
    if(!rst_n)
        cnt_v <= 0;
    else if(add_cnt_v) begin
        if(end_cnt_v)
            cnt_v <= 0;
        else
            cnt_v <= cnt_v + 1;
    end
end

assign add_cnt_v = end_cnt_h;
assign end_cnt_v = add_cnt_v && cnt_v==V_TOTAL-1;
//==========================================================================
//==    数据请求,比数据提前一拍
//==========================================================================
assign ch0_VGA_req = (cnt_h >= H_SYNC + H_BACK             ) && (cnt_h < H_SYNC + H_BACK + H_ADDR*1/4) &&
                     (cnt_v >= V_SYNC + V_BACK             ) && (cnt_v < V_SYNC + V_BACK + V_ADDR*1/2);

assign ch1_VGA_req = (cnt_h >= H_SYNC + H_BACK + H_ADDR*1/4) && (cnt_h < H_SYNC + H_BACK + H_ADDR*2/4) &&
                     (cnt_v >= V_SYNC + V_BACK             ) && (cnt_v < V_SYNC + V_BACK + V_ADDR*1/2);

assign ch2_VGA_req = (cnt_h >= H_SYNC + H_BACK + H_ADDR*2/4) && (cnt_h < H_SYNC + H_BACK + H_ADDR*3/4) &&
                     (cnt_v >= V_SYNC + V_BACK             ) && (cnt_v < V_SYNC + V_BACK + V_ADDR*1/2);

assign ch3_VGA_req = (cnt_h >= H_SYNC + H_BACK + H_ADDR*3/4) && (cnt_h < H_SYNC + H_BACK + H_ADDR*4/4) &&
                     (cnt_v >= V_SYNC + V_BACK             ) && (cnt_v < V_SYNC + V_BACK + V_ADDR*1/2);

assign ch4_VGA_req = (cnt_h >= H_SYNC + H_BACK             ) && (cnt_h < H_SYNC + H_BACK + H_ADDR*1/4) &&
                     (cnt_v >= V_SYNC + V_BACK + V_ADDR*1/2) && (cnt_v < V_SYNC + V_BACK + V_ADDR*2/2);

assign ch5_VGA_req = (cnt_h >= H_SYNC + H_BACK + H_ADDR*1/4) && (cnt_h < H_SYNC + H_BACK + H_ADDR*2/4) &&
                     (cnt_v >= V_SYNC + V_BACK + V_ADDR*1/2) && (cnt_v < V_SYNC + V_BACK + V_ADDR*2/2);

assign ch6_VGA_req = (cnt_h >= H_SYNC + H_BACK + H_ADDR*2/4) && (cnt_h < H_SYNC + H_BACK + H_ADDR*3/4) &&
                     (cnt_v >= V_SYNC + V_BACK + V_ADDR*1/2) && (cnt_v < V_SYNC + V_BACK + V_ADDR*2/2);

assign ch7_VGA_req = (cnt_h >= H_SYNC + H_BACK + H_ADDR*3/4) && (cnt_h < H_SYNC + H_BACK + H_ADDR*4/4) &&
                     (cnt_v >= V_SYNC + V_BACK + V_ADDR*1/2) && (cnt_v < V_SYNC + V_BACK + V_ADDR*2/2);
//==========================================================================
//==    数据使能,打1拍有细条纹,打2拍则没有
//==========================================================================
always @(posedge clk) begin 
        ch0_VGA_de_r1 <= ch0_VGA_req;
        ch1_VGA_de_r1 <= ch1_VGA_req;
        ch2_VGA_de_r1 <= ch2_VGA_req;
        ch3_VGA_de_r1 <= ch3_VGA_req;
        ch4_VGA_de_r1 <= ch4_VGA_req;
        ch5_VGA_de_r1 <= ch5_VGA_req;
        ch6_VGA_de_r1 <= ch6_VGA_req;
        ch7_VGA_de_r1 <= ch7_VGA_req;
        
        ch0_VGA_de_r2 <= ch0_VGA_de_r1;
        ch1_VGA_de_r2 <= ch1_VGA_de_r1;
        ch2_VGA_de_r2 <= ch2_VGA_de_r1;
        ch3_VGA_de_r2 <= ch3_VGA_de_r1;
        ch4_VGA_de_r2 <= ch4_VGA_de_r1;
        ch5_VGA_de_r2 <= ch5_VGA_de_r1;
        ch6_VGA_de_r2 <= ch6_VGA_de_r1;
        ch7_VGA_de_r2 <= ch7_VGA_de_r1;
end
//==========================================================================
//==    VGA端口输出
//==========================================================================
//时钟
assign VGA_clk = clk;

//行场同步
assign VGA_hsync = (cnt_h <= H_SYNC - 1) ? 0 : 1;
assign VGA_vsync = (cnt_v <= V_SYNC - 1) ? 0 : 1;

//数据
assign VGA_data = ch0_VGA_de_r2 ? ch0_VGA_din : // WHITE  : //
                  ch1_VGA_de_r2 ? ch1_VGA_din : // RED    : //
                  ch2_VGA_de_r2 ? ch2_VGA_din : // ORANGE : //
                  ch3_VGA_de_r2 ? ch3_VGA_din : // YELLOW : //
                  ch4_VGA_de_r2 ? ch4_VGA_din : // GREEN  : //
                  ch5_VGA_de_r2 ? ch5_VGA_din : // CYAN   : //
                  ch6_VGA_de_r2 ? ch6_VGA_din : // BLUE   : //
                  ch7_VGA_de_r2 ? ch7_VGA_din : // PURPLE : //
                  16'b0;


endmodule

4、效果展示

image

image

 

  学好 FPGA,然后离开 FPGA,也许这是我最后一篇 FPGA 博客了吧。

  再见各位,ASIC 上继续奔跑吧!

posted @ 2026-01-11 14:34  咸鱼IC  阅读(5)  评论(0)    收藏  举报