当前位置: 首页 > article >正文

dma_ddr 的编写 通过mig控制ddr3

在这里插入图片描述
此外还有别的模块 本模块是 其中一个

`timescale 1ns/1ps
module dma_ctrl (
    input   wire            ui_clk          ,   //100MHZ 用户时钟
    input   wire            ui_rst_n        ,
    //写fifo的写端口    
    input   wire            wf_wr_clk       ,   //由数据产生模块的时钟来决定
    input   wire            wf_wr_en        ,
    input   wire    [15:0]  wf_wr_data      ,
    //读fifo的读端口
    input   wire            rf_rd_clk       ,   //由数据接收模块的时钟来决定
    input   wire            rf_rd_en        ,
    output  wire    [15:0]  rf_rd_data      ,
    output  reg             rf_rd_req       ,   //数据请求接收信号
    //----native接口------  
    //命令控制端口
    output  wire    [27:0]	app_addr        ,      
    output  reg     [2:0]	app_cmd         ,  
    output  reg     		app_en          ,  
    input   wire    		app_rdy         ,  
    //写数据端口
    output  wire    [127:0]	app_wdf_data    ,          
    output  wire    		app_wdf_end     ,          
    output  reg     		app_wdf_wren    ,          
    input   wire    		app_wdf_rdy     ,      
    output  wire    [15:0]	app_wdf_mask    ,          
    //读数据端口
    input   wire    [127:0]	app_rd_data     ,          
    input   wire    		app_rd_data_end ,  
    input   wire    		app_rd_data_vali     
);

parameter FIFO_BURST_LEN = 128; //16*8
parameter ADDR_AMX       = 40000;   //200*200

localparam IDLE    = 3'b001;    //空闲
localparam WR_DATA = 3'b010;    //写
localparam RD_DATA = 3'b100;    //读

reg [2:0] c_state,n_state;

wire [7 : 0] wf_data_count; //写fifo中还剩多少个数据(128bit)

wire [7 : 0] rf_data_count; //读fifo中还剩多少个数据(128bit)

reg [8:0] cnt_addr; //地址计数器 0 - 127

reg [31:0] cnt_wr_data; //写数据个数计数器

reg    [27:0]	app_wr_addr;    //写地址线
reg    [27:0]	app_rd_addr;    //读地址线

reg flag;   //防止程序一上电就进入读数据状态,防止读空
wire wf_rd_en;  

assign wf_rd_en     = app_wdf_wren && app_wdf_rdy;  
assign app_addr     = (c_state == WR_DATA ) ? app_wr_addr : app_rd_addr;
assign app_wdf_end  = app_wdf_wren;
assign app_wdf_mask = 0;

always @(posedge ui_clk ) begin
    if(!ui_rst_n)
        flag <= 0;
    else if(app_wr_addr == ADDR_AMX >> 2)
        flag <= 1;
    else
        flag <= flag;
end

//----三段式状态机。一 。将次态赋值给现态
always @(posedge ui_clk ) begin
    if(!ui_rst_n)
        c_state <= IDLE;
    else
        c_state <= n_state;
end

//----三段式状态机。二 。状态跳转描述
always @(*) begin
    if(!ui_rst_n)
        n_state = IDLE;
    else begin
        case (c_state)
                IDLE    : begin
                    if(wf_data_count > FIFO_BURST_LEN)
                        n_state = WR_DATA;
                    else if(rf_data_count < FIFO_BURST_LEN && flag)
                        n_state = RD_DATA;
                    else
                        n_state = IDLE;
                end
                WR_DATA : begin
                    if(app_en && app_rdy && cnt_addr == FIFO_BURST_LEN - 1)
                        n_state = IDLE;
                    else
                        n_state = WR_DATA;
                end
                RD_DATA : begin
                    if(app_en && app_rdy && cnt_addr == FIFO_BURST_LEN - 1)
                        n_state = IDLE;
                    else
                        n_state = RD_DATA;
                end
            default: n_state = IDLE;
        endcase
    end
end

//----三段式状态机。三 。对中间变量及输出结果赋值
always @(posedge ui_clk ) begin
    if(!ui_rst_n)
        rf_rd_req <= 0;
    else if(rf_data_count > 100)
        rf_rd_req <= 1;
    else
        rf_rd_req <= rf_rd_req;
end

always @(posedge ui_clk ) begin
    if(!ui_rst_n)
        app_wr_addr <= 0;
    else if(c_state == WR_DATA && app_en && app_rdy)begin
        if(app_wr_addr == ADDR_AMX - 8) //固定突发长度:8
            app_wr_addr <= 0;
        else
            app_wr_addr <= app_wr_addr + 8;
    end
    else
        app_wr_addr <= app_wr_addr;
end

always @(posedge ui_clk ) begin
    if(!ui_rst_n)
        app_rd_addr <= 0;
    else if(c_state == RD_DATA && app_en && app_rdy)begin
        if(app_rd_addr == ADDR_AMX - 8) //固定突发长度:8
            app_rd_addr <= 0;
        else
            app_rd_addr <= app_rd_addr + 8;
    end
    else
        app_rd_addr <= app_rd_addr;
end

always @(posedge ui_clk ) begin
    if(!ui_rst_n)
        app_cmd <= 0;
    else if(c_state == WR_DATA)
        app_cmd <= 0;
    else if(c_state == RD_DATA)
        app_cmd <= 1;
    else
        app_cmd <= app_cmd;
end

always @(posedge ui_clk ) begin
    if(!ui_rst_n)
        app_en <= 0;
    else if(c_state == WR_DATA || c_state == RD_DATA)begin
        if(cnt_addr == FIFO_BURST_LEN - 1 && app_rdy)
            app_en <= 0;
        else
            app_en <= 1;
    end
    else
        app_en <= 0;
end

always @(posedge ui_clk ) begin
    if(!ui_rst_n)
        app_wdf_wren <= 0;
    else if(c_state == WR_DATA && app_wdf_rdy)begin
        if(cnt_wr_data == FIFO_BURST_LEN - 1 )
            app_wdf_wren <= 0;
        else
            app_wdf_wren <= 1;
    end
    else
        app_wdf_wren <= 0;
end

always @(posedge ui_clk ) begin
    if(!ui_rst_n)
        cnt_wr_data <= 0;
    else if(c_state == WR_DATA)begin
        if(cnt_wr_data == FIFO_BURST_LEN - 1 && app_wdf_wren && app_wdf_rdy)
            cnt_wr_data <= cnt_wr_data; 
        else if(app_wdf_wren && app_wdf_rdy)    
            cnt_wr_data <= cnt_wr_data + 1;
        else
            cnt_wr_data <= cnt_wr_data;
    end
    else
        cnt_wr_data <= 0;
end

wf_fifo wf_fifo_u (
  .wr_clk(wf_wr_clk),                // input wire wr_clk
  .rd_clk(ui_clk),                // input wire rd_clk
  .din(wf_wr_data),                      // input wire [15 : 0] din
  .wr_en(wf_wr_en),                  // input wire wr_en
  .rd_en(wf_rd_en),                  // input wire rd_en
  .dout(app_wdf_data),                    // output wire [127 : 0] dout
//   .full(full),                    // output wire full
//   .empty(empty),                  // output wire empty
  .rd_data_count(wf_data_count)  // output wire [7 : 0] rd_data_count
);

rf_fifo rf_fifo_u (
  .wr_clk(ui_clk),                // input wire wr_clk
  .rd_clk(rf_rd_clk),                // input wire rd_clk
  .din(app_rd_data),                      // input wire [127 : 0] din
  .wr_en(app_rd_data_vali),                  // input wire wr_en
  .rd_en(rf_rd_en),                  // input wire rd_en
  .dout(rf_rd_data),                    // output wire [15 : 0] dout
//   .full(full),                    // output wire full
//   .empty(empty),                  // output wire empty
  .wr_data_count(rf_data_count)  // output wire [7 : 0] wr_data_count
);
    
endmodule

http://www.kler.cn/a/547978.html

相关文章:

  • Java 大视界 -- 云计算时代 Java 大数据的云原生架构与应用实践(86)
  • PHP代驾系统小程序
  • 使用瑞芯微RK3588的NPU进行模型转换和推理
  • STM32——HAL库开发笔记17(中断的概念)(参考来源:b站铁头山羊)
  • Spring Boot 携手 DeepSeek:开启智能交互新时代
  • mongodb主从
  • AI驱动的广告制作革命:Icon如何实现从创意到成片的全流程自动化
  • java在文本追加内容时候发现数据丢失问题
  • SpringBoot多数据源实践:基于场景的构建、实现和事务一体化研究
  • 如何运用边缘计算控制器提升智能工厂的竞争力?
  • 【java】方法的基本内存原理(栈和堆)
  • golang使用redis实现全文搜索
  • 建造者模式构建对象
  • CentOS7 安装配置FTP服务
  • 鸿蒙开发:熟知@BuilderParam装饰器
  • STM32F10X 启动文件完整分析
  • Xilinx FPGA开发指南-7系列FPGA配置引脚定义
  • Vue 3 30天精进之旅:Day 25 - PWA支持
  • 学习sql的资源:sql练习平台;在线编辑器,免费sql教程,免费sql书籍
  • (LLaMa Factory)大模型训练方法--监督微调(Qwen2-0.5B)