微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > quratus 乒乓

quratus 乒乓

时间:10-02 整理:3721RD 点击:
这里测试数据从ROM里读,用两个64words的RAM来实现乒乓。
先看一下RAM ipcore的特征,在配置时先看一下配置方式就是有锁存器



在生成的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

assign wr_en_ram0=(!wr_cs)?din_valid:1'b0;

assign wr_en_ram1=(wr_cs)?din_valid:1'b0;

always @(negedge rst,posedge clk) begin

      if(!rst)begin

           wr_addr<='d0;

      end

      elseif(din_valid) begin

           if(wr_addr_end)begin

                 wr_addr<='d0;

           end

           elsebegin

                 wr_addr<=wr_addr+1'd1;

           end

      end

      else begin

           wr_addr<=wr_addr;

      end

end

assign wr_addr_end=(wr_addr==RAM_ADDR-1)?1'b1:1'b0;

always @(negedge rst,posedge clk) begin

      if(!rst)begin

           rd_cs<=1'b0;

      end

      elseif(rd_addr_end) begin

           rd_cs<=~rd_cs;

      end

      else begin

           rd_cs<=rd_cs;

      end

end

always @(negedge rst,posedge clk) begin

      if(!rst)begin

           rd_en<=1'b0;

      end

      elseif(wr_addr_end) begin

           rd_en<=1'b1;

      end

      else begin

           rd_en<=rd_en;

      end

end

always @(negedge rst,posedge clk) begin

      if(!rst)begin

           rd_addr<='d0;

      end

      elseif(rd_en) begin

           if(rd_addr_end)begin

                 rd_addr<='d0;

           end

           elsebegin

                 rd_addr<=rd_addr+1'd1;

           end

      end

end

assign rd_addr_end=(rd_addr==RAM_ADDR-1)?1'b1:1'b0;

always @(negedge rst,posedge clk) begin

      if(!rst)begin

           dout_valid<=1'b0;

      end

      else begin

           dout_valid<=rd_en;

      end

end

always @(negedge rst,posedge clk) begin

      if(!rst)begin

           rd_cs_dl<=1'b0;

      end

      else begin

           rd_cs_dl<=rd_cs;

      end

end

assign dout=(!rd_cs_dl)?data_ram0:data_ram1;

myram_ipcore myram0(

.clock(clk),

.data(din),

.rdaddress(rd_addr),

.rden(1'b1),

.wraddress(wr_addr),

.wren(wr_en_ram0),

.q(data_ram0)

);

myram_ipcore myram1(

.clock(clk),

.data(din),

.rdaddress(rd_addr),

.rden(1'b1),

.wraddress(wr_addr),

.wren(wr_en_ram1),

.q(data_ram1)

);

endmodule


再发一个FIFO 乒乓代码
用FIFO做乒乓,先了解FIFO IPCORE
myfifo_ipcore (
        clock,
        data,
        rdreq,
        wrreq,
        empty,
        full,
        q,
        usedw);
写使能wrreq和写入第一个数据data同步,当FIFO中最后一个内存被写入数据,full实时置高;读使能rdreq置高下一个时钟,读出第一个数q,FIFO中有第一个数后一个时钟empty置高。
写控制:
1.        初始复位,wr_cs置低,默认第一个片子;
2.        实时判断两个片子写满状态full,第一个片子写满,wr_cs置高,选通第二个片子,
第二个片子写满,wr_cs置低,选通第一个片子,并锁存状态直到下一次触发;
3.        写使能实时和wr_cs同步。
读控制:
1.        初始复位,总读使能置低,当第一个芯片满状态,置高并锁存;
2.        读使能和写片选实时同步,写第一个片子读第二个片子,写第二个片子就读第一个
片子,读使能要挂到总读使能上,就好像写使能要挂在总数据有效上一样;
3.        总读使能有效后一个时钟输出数据有效;
4.        总读使能,时钟采集满状态,当写满一个片子后,读数据片子取反。
module mypp64(
input rst,
input clk,
input[15:0] din,
input din_valid,
output[15:0] dout,
output reg dout_valid
);
wire wr_cs;
reg rd_cs;
wire wr_en_fifo0;
wire wr_en_fifo1;
wire rd_en_fifo0;
wire rd_en_fifo1;
wire full_fifo0;
wire full_fifo1;
wire rd_en;
wire[15:0] dout_fifo0;
wire[15:0] dout_fifo1;
assign wr_cs=(!rst)?1'b0:(full_fifo0)?1'b1:(full_fifo1)?1'b0:wr_cs;
assign rd_en=(!rst)?1'b0:(full_fifo0)?1'b1:rd_en;
assign wr_en_fifo0=(!wr_cs)?din_valid:1'b0;
assign wr_en_fifo1=(wr_cs)?din_valid:1'b0;
assign rd_en_fifo0=(!rst)?1'b0:(wr_cs)?rd_en:1'b0;
assign rd_en_fifo1=(!rst)?1'b0:(!wr_cs)?rd_en:1'b0;
always @(negedge rst,posedge clk) begin
        if(!rst) begin
                dout_valid<=1'b0;
        end
        else if(rd_en)begin
                dout_valid<=1'b1;
        end
        else begin
                dout_valid<=dout_valid;
        end
end
always @(negedge rst,posedge clk) begin
        if(!rst) begin
                rd_cs<=1'b0;
        end
        else if(rd_en) begin
                if(full_fifo0 || full_fifo1) begin
                                rd_cs<=~rd_cs;
                end
                else begin
                                rd_cs<=rd_cs;
                end
        end
        else begin
                rd_cs<=rd_cs;
        end
end
assign dout=(rd_cs)?dout_fifo0:dout_fifo1;
myfifo_ipcore fifo0(
.clock(clk),
.data(din),
.rdreq(rd_en_fifo0),
.wrreq(wr_en_fifo0),
.empty(),
.full(full_fifo0),
.q(dout_fifo0),
.usedw()
);
myfifo_ipcore fifo1(
.clock(clk),
.data(din),
.rdreq(rd_en_fifo1),
.wrreq(wr_en_fifo1),
.empty(),
.full(full_fifo1),
.q(dout_fifo1),
.usedw()
);
endmodule

顶  不错哦  研究下

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top