RAM双端口
设计目标:
- 调用一个双端口ram,数据位宽是16,深度是1024,要求0地址写入数据为0,1地址数据写1…1023地址数据写入1023,倒序将数据读出。
- 调用一个双端口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