在生成的ipcore中
altsyncram_component.outdata_reg_a ="UNREGISTERED",就是无寄存器
altsyncram_component.outdata_reg_a ="CLOCK0",就是有寄存器
发现连了时钟线的就是有锁存器,没连时钟线的就是没锁存器。很可能有时钟触发的就是always@(edge clk),没有时钟就是assign A=B,所以有时钟触发里有锁存器,没有就是总线输入输出,没锁存器。
双口RAM,不选择输出有寄存器的使用方法:
1. 写使能,第一个写地址,第一个写数据在同步赋值。
2. 读使能一直有效,读地址在和读出第一个数据间有一个时钟延时,那么第一个数据
读出时正好读地址开始递增1。
虽然读出数据没有寄存器,但读地址有寄存器,所以读地址比读出数据快一个时钟;而写RAM时,地址和数据都有寄存器,所以两个是同步赋值,触发条件就是这里的写使能信号,所以三者要同时赋值,在写使能赋值下一个时钟,读进去地址和数据锁存器里的值。
自己编写pingpang
读出ROM里1024个点,用两个64 words的RAM做乒乓读出
随着第一个数据有效信号,出现了第一个数据。
写RAM部分:
1. 初始的复位状态:写片选默认为第一个片,写地址为0;
2. 第一个数据进来,写地址判断数据有效信号自增1,由于是时钟触发,地址寄存器
出现锁存器,要到下一个时钟才递增,故地址与读入数据同步对应;
3. 当地址为最后一个地址时,实时触发一个flag,时钟采集这个flag,下一个时钟采
集到,地址回到0,此时片选RAM写使能切换到下一块RAM,如此循环反复。
读RAM部分:
1. 初始状态:默认读第一个芯片,读地址为0,写使能一直有效;
2. 时钟采集第一次写末地址的flag时,写地址使能(写地址使能不是写使能),此时
已经是写地址归0,读地址为0;
3. 写地址采集到写地址使能,此时已经是又下一个时钟,此时写地址为1,读地址自
增1,也为1,读出第一个片子的第一个数据,而第二个片子准备好了写入数据和写入数据地址,实际写入的也是第一个数据,此时读地址和写地址同步;
4. 读地址为末时,读出前一个数据,实时触发一个flag,时钟采集这个flag,下一个
时钟采集到,给读片选切换,读地址清零,保留一次片选寄存器,即在用时钟赋值片选寄存器值,此时已经过去了两个时钟,也就是说读地址为1,读出的数据为另一块片子的0地址,即首地址,实时判断片选寄存器值来选择从哪块RAM中读数据。
这里两个芯片切换,写切换的是使能切换,读切换是哪个芯片读出数据切换。写地址增加使能和数据有效同步,读地址使能要等到写到完第一个片子才有效。读写的地址都是可以复用的,用写使能和读数据确定片子。
写RAM地址和数据同步,读RAM地址比数据快一个时钟,所以读切换时多一个时钟延迟。
64个words RAM做乒乓代码:
module pp64(
input rst,
input clk,
input[15:0] din,
input din_valid,
output[15:0] dout,
output reg dout_valid
);
parameter RAM_ADDR=64;
parameter RAM_WIDTH=6;
reg wr_cs;
wire wr_en_ram0;
wire wr_en_ram1;
reg[RAM_WIDTH-1:0] wr_addr;
wire wr_addr_end;
reg rd_cs;
reg rd_cs_dl;
reg rd_en;
reg[RAM_WIDTH-1:0] rd_addr;
wire rd_addr_end;
wire[15:0] data_ram0;
wire[15:0] data_ram1;
always @(negedge rst,posedge clk) begin
if(!rst)begin
wr_cs<=1'b0;
end
elseif(wr_addr_end) begin
wr_cs<=~wr_cs;
end
else begin
wr_cs<=wr_cs;
end
end
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |