FPGA--verilog 实现乒乓操作(附代码)

乒乓操作原理

乒乓操作整体流程图如下图所示:
在这里插入图片描述
乒乓操作的原理简单点说就是:
控制两个存储RAM1和RAM2,当数据开始存储进入RAM1时,将RAM2的数据输出进行处理;当数据开始存储进入RAM2时,将RAM1的数据输出进行处理。
何时存储数据由输入数据流选择模块控制,何时输出,由输出数据流选择模块进行控制。

RTL 图

在这里插入图片描述
整体RTL图如图所示:
其中 :
controller为控制模块,主要生成控制两个选择模块的使能信号。
mux21为输入数据流选择模块,控制两个RAM数据流何时输入。
RAM1和RAM2为两个存储模块,用于存储输入的数据流。
mux22为输出数据流控制模块,用于选择两个RAM的数据流,进行输出。

代码编写

下面对各个模块代码进行具体介绍:
顶层模块:

module dpram_pingpang_top(
input clk,
input rst_n,
input [15:0] i_data,

output [15:0] o_data,
//test
output [7:0] o_addr,
output [7:0] o_addw
    );
    
    wire mux1_en;
    wire mux2_en;
    
     controller controller_m1(
   .clk(clk),
   .rst_n(rst_n),
    .mux1_en(mux1_en),
    .mux2_en(mux2_en)
       );
    wire wr_en1;
    wire wr_en2;
    
    mux21 mux21_m1(
       .clk(clk),
       .rst_n(rst_n),
       .en1(mux1_en),
        .wr_en1(wr_en1),
        .wr_en2(wr_en2)
       );
       wire [15:0] o_data1;
      DRAM DRAM_m1(
       .clk(clk),
       .rst_n(rst_n),
       .data(i_data),
       .wr_en(wr_en1),
       .o_data(o_data1),
       .o_addr(o_addr),
       .o_addw(o_addw)
           );
     wire [15:0] o_data2;
     DRAM DRAM_m2(
        .clk(clk),
        .rst_n(rst_n),
        .data(i_data),
        .wr_en(wr_en2),
        .o_data(o_data2)
        //.o_addr(o_addr),
        //.o_addw(o_addw)
                      ); 
        
        mux22 mux22_m1(
         .clk(clk),
         .rst_n(rst_n),
         .wr_en(mux1_en),
         .o_data1(o_data1),
         .o_data2(o_data2),
         .o_data(o_data)
            );
endmodule

顶层模块主要包含控制模块controller,两个RAM模块,两个mux二选一模块。

控制模块 controller

module controller(
input clk,
input rst_n,

output reg mux1_en,
output reg mux2_en
    );

reg [7:0] cnt; //0-255
always@(posedge clk or negedge rst_n)
begin
    if(rst_n ==1'b0)
        cnt <= 'd0;
    else if(cnt =='d255)
        cnt <='d0;
    else
        cnt <= cnt +'d1;
end

always@(posedge clk or negedge rst_n)
begin
    if(rst_n ==1'b0)
    begin
        mux1_en <='d0;
        mux2_en <='d0;
    end
    else if(cnt <'d128)
    begin
        mux1_en <= 'd1;
        mux2_en <= 'd0;
    end
    else if(cnt >'d127&&cnt <'d256)
    begin
        mux1_en <='d0;
        mux2_en <='d1;
    end
end

endmodule

控制模块主要控制两个mux选择器的使能信号。

输入数据二选一选择器mux21:

module mux21(
input clk,
input rst_n,
input en1,

output wr_en1,
output wr_en2
    );
    
assign wr_en1 = en1;
assign wr_en2 =~en1;
endmodule

由controller模块可知:计数0-255,在0-127时往RAM1中写入数据,读取RAM2中的数据;128-255时,往RAM2中写入数据,读取RAM1中的数据。

RAM存储模块:

module DRAM(
input clk,
input rst_n,
input [15:0] data,
input wr_en,

output reg [15:0] o_data,
output reg [7:0] o_addr,
output reg [7:0] o_addw
    );
    
always@(posedge clk or negedge rst_n)
begin
    if(rst_n ==1'b0)
    begin
        o_addr <='d0;
        o_addw <='d0;
    end
    else if(wr_en)
    begin
        o_addw <=o_addw+'d1;
        o_addr <='d0;
    end
    else if(!wr_en)
    begin
        o_addr <= o_addr +'d1;
        o_addw <='d0;
    end
end

reg [15:0] aRAM[127:0];
integer i;

always@(posedge clk or negedge rst_n)
begin
    if(rst_n ==1'b0)
    begin
        o_data <='d0;
        for(i=0;i<=127;i=i+1)
        aRAM[i] <='d0;
    end
    else if(wr_en)
    begin
    aRAM[o_addw]<=data;
    o_data <='d0;
    end
    else if(!wr_en)
    begin
    o_data<=aRAM[o_addr];
    end
end
endmodule

加入o_addr和o_addw两个信号用来观察RAM读和RAM写的地址,当RAM进行读操作时,o_addr地址每个时钟+1;当RAM进行写操作时,o_addw地址每个时钟+1.

输出数据二选一模块mux22:

module mux22(
input clk,
input rst_n,
input wr_en,
input [15:0] o_data1,
input [15:0] o_data2,

output [15:0] o_data
    );
reg flag1;
reg flag2; //打两拍

always@(posedge clk or negedge rst_n)
begin
    if(rst_n ==1'b0)
    begin
        flag1 <='d0;
        flag2 <='d0;
    end
    else
    begin
        flag1 <= wr_en;
        flag2 <= flag1;
    end
end

reg [15:0] din1;
reg [15:0] din2;
always@(posedge clk or negedge rst_n)
begin
    if(rst_n ==1'b0)
    begin
        din1 <='d0;
        din2 <='d0;
    end
    else
    begin
        din1 <=o_data1;
        din2 <=o_data2;
    end
end

assign o_data =(flag2=='d1)?din2:din1;
endmodule

对输出的数据进行选择,这里直接用controller模块输出的使能信号来控制即可。

进行仿真testbench测试后,其仿真如图所示:
在这里插入图片描述
RAM1和RAM2的使能信号en1和en2交替为高,这里拉出来RAM1模块的o_addr和o_addw信号,o_addr为0时表示RAM1此时为读操作,o_addw为高表示此时RAM1为写操作。

附工程代码(vivado版本2017.4)
https://download.csdn.net/download/weixin_44413306/87234366

  • 12
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
DDR乒乓操作是指在Verilog中使用双数据率(DDR)技术进行乒乓操作。在给定的Verilog代码中,有两个RAM模块(RAM1和RAM2),它们的使能信号(en1和en2)交替为高。当RAM1的o_addr为0时,表示RAM1正在进行读操作,而o_addw为高时,表示RAM1正在进行写操作。\[1\] 在提供的测试台(testbench)代码中,定义了时钟信号(clk)、复位信号(rst_n)和数据输入信号(data_in),以及数据输出信号(data_out)。通过对时钟信号进行周期性翻转,产生20ns的时钟周期。在初始化阶段,将时钟和复位信号设置为初始值,并在一定时间后将复位信号拉高。然后,通过每10个时钟周期翻转一次时钟信号,产生输入激励。\[2\] RAM存储模块(DRAM)定义了时钟信号(clk)、复位信号(rst_n)、数据输入信号(data)、写使能信号(wr_en),以及数据输出信号(o_data)、地址输出信号(o_addr)和写地址输出信号(o_addw)。在时钟上升沿或复位信号下降沿触发的always块中,根据不同的情况对输出信号进行更新。当复位信号为低电平时,将地址输出信号和写地址输出信号设置为0。当写使能信号为高时,将写地址输出信号递增1,地址输出信号设置为0。当写使能信号为低时,将地址输出信号递增1,写地址输出信号设置为0。同时,使用一个数组aRAM来存储数据,并根据读写操作对数据进行更新。\[3\] 综上所述,DDR乒乓操作是通过交替使用两个RAM模块,并根据读写操作对数据进行更新,实现数据的双数据率操作。 #### 引用[.reference_title] - *1* *3* [verilog 实现乒乓操作代码)](https://blog.csdn.net/weixin_44413306/article/details/128153149)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [FPGA设计——verilog实现乒乓操作并modelsim仿真](https://blog.csdn.net/H19981118/article/details/125103589)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值