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文章来源地址https://uudwc.com/A/z0yR

原文地址:https://blog.csdn.net/weixin_44413306/article/details/128153149

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年06月16日 02:28
基于Vivado和Ego1的密码锁设计
下一篇 2023年06月16日 02:28