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
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值