FPAG学习RAM双端口

RAM双端口

设计目标:

  1. 调用一个双端口ram,数据位宽是16,深度是1024,要求0地址写入数据为0,1地址数据写1…1023地址数据写入1023,倒序将数据读出。
  2. 调用一个双端口ram,数据位宽是16,深度是1024,要求0地址写入数据为2,1地址数据写3…1023地址数据写入1,数据从700开始倒着读,读到0的时候,从1023再读到700,要求写时钟为100MHZ,读时钟为20MHZ。

倒序

时序图

在这里插入图片描述

代码

module ram (
    input wire clk,
    input wire rst_n,
    output wire [15:0]q
);

reg [9:0]cnt1;
reg [1:0]cnt2;
reg [15:0]data;
reg [9:0]write_addr;
reg [9:0]read_addr;
reg wen;

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        cnt1 <= 10'd0;
    end
    else if (cnt1 == 10'd1023) begin
        cnt1 <= 10'd0;
    end    
    else begin
        cnt1 <= cnt1 + 10'd1;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        cnt2 <= 2'd0;
    end
    else if (cnt2 == 3'd3 && cnt1 == 10'd1023) begin
        cnt2 <= 2'd0;
    end
    else if (cnt1 == 10'd1023) begin
        cnt2 <= cnt2 + 10'd1;
    end
    else begin
        cnt2 <= cnt2;
    end
end
    
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        wen <= 1'b0;
    end
    else if (cnt2 == 2'd0 && cnt1 == 10'd1023) begin
        wen <= ~wen;
    end
    else if (cnt2 == 2'd1 && cnt1 == 10'd1023) begin
        wen <= ~wen;
    end
    else begin
        wen <= wen;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        read_addr <= 10'd0;

    end
    else if (cnt2 == 2'd2 && cnt1 == 10'd1023) begin
        read_addr <= 10'd1023;
    end
    else if (cnt2 == 2'd3) begin
        read_addr <= read_addr - 10'd1;
    end
    else begin
        read_addr <= 10'd0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        write_addr <= 10'd0;
    end
    else if (cnt1 == 10'd1023) begin
        write_addr <= 10'd0;
    end
    else begin
        write_addr <= write_addr + 10'd1;
    end
end


always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        data <= 16'd0;
    end
    else if (cnt1 == 10'd1023) begin
        data <= 16'd0;
    end
    else begin
        data <= data + 10'd1;
    end
end


ip_ram_sim2port	ip_ram_sim2port_inst (
	.clock ( clk ),
	.data ( data ),
	.rdaddress ( read_addr ),
	.wraddress ( write_addr ),
	.wren ( wen ),
	.q ( q )
);

endmodule

仿真

在这里插入图片描述

乱序

时序图

时序图

代码

module ram_2clk_sim (
    input wire write_clk,
    input wire read_clk,
    input wire rst_n,
    output wire [15:0]q
);
    
reg [9:0]cnt1;
reg [1:0]cnt2;
reg [9:0]cnt3;
reg [1:0]cnt4;
reg [15:0]data;
reg [9:0]write_addr;
reg [9:0]read_addr;
reg wen;
reg ren;

always @(posedge write_clk or negedge rst_n) begin
    if (~rst_n) begin
        cnt1 <= 10'd0;
    end
    else if (cnt1 == 10'd1023) begin
        cnt1 <= 10'd0;
    end    
    else begin
        cnt1 <= cnt1 + 10'd1;
    end
end

always @(posedge write_clk or negedge rst_n) begin
    if (~rst_n) begin
        cnt2 <= 2'd0;
    end
    else if (cnt2 == 3'd3 && cnt1 == 10'd1023) begin
        cnt2 <= 2'd0;
    end
    else if (cnt1 == 10'd1023) begin
        cnt2 <= cnt2 + 10'd1;
    end
    else begin
        cnt2 <= cnt2;
    end
end
    
always @(posedge write_clk or negedge rst_n) begin
    if (~rst_n) begin
        wen <= 1'b0;
    end
    else if (cnt2 == 2'd0 && cnt1 == 10'd1021) begin
        wen <= ~wen;
    end
    else if (cnt2 == 2'd1 && cnt1 == 10'd1021) begin
        wen <= ~wen;
    end
    else begin
        wen <= wen;
    end
end


always @(posedge write_clk or negedge rst_n) begin
    if (~rst_n) begin
        write_addr <= 10'd0;
    end
    else if (cnt1 == 10'd1023) begin
        write_addr <= 10'd0;
    end
    else if (cnt1 == 10'd1021) begin
        write_addr <= 10'd1022;
    end
    else begin
        write_addr <= write_addr + 10'd1;
    end
end


always @(posedge write_clk or negedge rst_n) begin
    if (~rst_n) begin
        data <= 16'd0;
    end
    else if (cnt1 == 10'd1021) begin
        data <= 16'd0;
    end
    else if (data == 16'd1023) begin
        data <= 16'd0;
    end
    else begin
        data <= data + 16'd1;
    end
end

always @(posedge read_clk or negedge rst_n) begin
    if (~rst_n) begin
        cnt3 <= 10'd0;
    end
    else if (cnt1 == 10'd1023) begin
        cnt3 <= 10'd0;
    end    
    else begin
        cnt3 <= cnt3 + 10'd1;
    end
end

always @(posedge read_clk or negedge rst_n) begin
    if (~rst_n) begin
        cnt4 <= 2'd0;
    end
    else if (cnt4 == 3'd3 && cnt3 == 10'd1023) begin
        cnt4 <= 2'd0;
    end
    else if (cnt3 == 10'd1023) begin
        cnt4 <= cnt4 + 10'd1;
    end
    else begin
        cnt4 <= cnt4;
    end
end 

always @(posedge read_clk or negedge rst_n) begin
    if (~rst_n) begin
        ren <= 1'b0;
    end
    else if (cnt4 == 2'd1 && read_addr == 10'd699) begin
        ren <= ~ren;
    end
    else if (cnt4 == 2'd2 && read_addr == 10'd699) begin
        ren <= ~ren;
    end
    else begin
        ren <= ren;
    end
end

always @(posedge read_clk or negedge rst_n) begin
    if (~rst_n) begin
        read_addr <= 10'd0;
    end
    else if (cnt3 == 10'd1023) begin
        read_addr <= 10'd1023;
    end
    else begin
        read_addr <= read_addr - 10'd1;
    end
end

ram_2clk	ram_2clk_inst (
	.data ( data ),
	.rdaddress ( read_addr ),
	.rdclock ( read_clk ),
	.rden ( ren ),
	.wraddress ( write_addr ),
	.wrclock ( write_clk ),
	.wren ( wen ),
	.q ( q )
);


//调用一个双端口ram,数据位宽是16,深度是1024,要求找到1024个地址中的最大值,并把最大值地址和数据一起输出出来
reg [9:0]max;
reg [9:0]max_addr;

always @(posedge read_clk or negedge rst_n) begin
    if (~rst_n) begin
        max <= 10'd0;
        max_addr <= 10'd0;
    end
    else if (max < q) begin
        max <= q;
        max_addr <= read_addr + 10'd1;
    end
    else begin
        max <= max;
        max_addr <= max_addr;
    end
end

endmodule

仿真

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FPGA端口RAM是一种常见的存储器组件,具有两个独立的读写端口,以支持多个并行访问。每个端口都有自己的地址和数据输入/输出。 使用端口RAM可以实现一些特定的应用场景,比如并行计算、数据缓存和通信协议处理等。下面是使用FPGA端口RAM的一般步骤: 1. 首先,在FPGA开发环境中创建一个新的项目,并将所需的端口RAM模块添加到设计中。这可以通过使用硬件描述语言(如Verilog或VHDL)来完成。 2. 在设计中定义每个端口的地址输入、数据输入和数据输出信号。通常情况下,每个端口都有一个地址输入信号(用于选择要访问的存储单元)、一个数据输入信号(用于写入数据)和一个数据输出信号(用于读取数据)。 3. 根据应用需求,为每个端口定义读写操作的时序和控制逻辑。这包括读写使能信号、读写时钟信号和读写操作的控制逻辑。 4. 在FPGA开发环境中生成RTL综合文件,并对其进行综合以生成逻辑网表。 5. 将逻辑网表映射到目标FPGA设备,并生成比特流文件。 6. 将比特流文件下载到FPGA设备中,并对其进行配置。 7. 在FPGA设备上进行仿真或验证,确保端口RAM在设计中的功能和性能都符合预期。 需要注意的是,具体的实现步骤可能会因使用的FPGA开发环境和目标设备而有所不同。因此,在实际应用中,建议参考相关的FPGA开发文档和手册,以确保正确地使用端口RAM

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值