在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 4453|回复: 6

[讨论] 【讨论|求助】verilog怎么写能综合出异步的RAM

[复制链接]
发表于 2018-10-13 15:36:07 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
先把代码贴出来,一段很简单的代码



  1. module asyn_ram
  2. #(parameter DWIDTH=4,//data width
  3.                                 AWIDTH=10)//address width
  4. (
  5.         input wr_clk,
  6.         input[DWIDTH-1:0] wr_data,
  7.         input wr_en,
  8.         input[AWIDTH-1:0] wr_addr,
  9.        
  10.         input  rd_clk,
  11.         output [DWIDTH-1:0] rd_data,
  12.         input  rd_en,
  13.         input[AWIDTH-1:0] rd_addr
  14. );

  15. reg[DWIDTH-1:0] rw_mem [2**AWIDTH-1:0];//define the memory
  16. reg[AWIDTH-1:0] raddr;
  17. always@(posedge wr_clk )
  18. begin
  19.         if(wr_en) begin
  20.                 rw_mem[wr_addr]<=wr_data;
  21.         end
  22. end

  23. always@(posedge rd_clk)
  24. begin
  25.         if(rd_en) begin
  26.                 raddr<=rd_addr;
  27.         end
  28. end
  29. assign rd_data=rw_mem[raddr];
  30. endmodule



复制代码


在quartus中综合后的RTL视图是这样的:
RY(3VPNOES(]GVN_6A]UGK4.png

这个和我的逻辑对不上呢,读时钟不是驱动数据的输出的
在technology map viewer中是这样的
UZL(IOGPS8[OM%VY0O{2426.png

这个是在FPGA中实际生成的,应该是对的,可是RTL为什么是错的呢?有朋友知道原因吗?
 楼主| 发表于 2018-10-13 16:37:55 | 显示全部楼层
回复 1# fucong_59
用modelsim仿真结果也是正确的
发表于 2018-10-13 21:59:12 | 显示全部楼层
这个跟工具有关,你要infer出异步ram, 要严格按照altera规定的coding style.
我试过Xilinx是可以的,你可以查一下altera有关文档。
你这个综合出的结果应该是
always @ rd_clk
begin
  if (rd_en)  rd_addr_int <= rdaddr
end
assign outdata = ram[rd_addr_int];
功能上讲也没啥问题

实在infer不了你就例化一个双口RAM肯定能解决的
 楼主| 发表于 2018-10-14 10:20:28 | 显示全部楼层
回复 3# gooseman

谢谢您的回答,我在网上找了altera的 Infer the RAM using the Verilog HDL template,网址:https://www.intel.com/content/www/us/en/programmable/quartushelp/15.0/mergedProjects/hdl/vlog/vlog_pro_ram_inferred.htm
用其中的ram dual template,代码如下:



  1. module ram_dual(q, addr_in, addr_out, d, we, clk1, clk2);
  2.    output[7:0] q;
  3.    input [7:0] d;
  4.    input [6:0] addr_in;
  5.    input [6:0] addr_out;
  6.    input we, clk1, clk2;

  7.    reg [6:0] addr_out_reg;
  8.    reg [7:0] q;
  9.    reg [7:0] mem [127:0];

  10.    always @(posedge clk1) begin
  11.       if (we)
  12.          mem[addr_in] <= d;
  13.    end

  14.    always @(posedge clk2) begin
  15.       q <= mem[addr_out_reg];
  16.       addr_out_reg <= addr_out;
  17.    end
  18.         
  19. endmodule


复制代码


但是综合后的RTL viewer是这样的
F75`ED{V7$N@BZH4VW`I)FN.png

另外我在Xilinx的ISE工具中RTL是一样的结果,综合后的technology schematic视图如下
W9M@U[5T2]2_]IIS77W$)NK.png

没有用例化IP的方法是因为调用反复修改宽度和深度很麻烦
 楼主| 发表于 2018-10-14 10:31:57 | 显示全部楼层
回复 3# gooseman

//不知道为什么刚刚回复没有显示,重新写一下
   谢谢您的回复,我在网上找了altera infer ram verilog template ,网址:https://www.intel.com/content/www/us/en/programmable/quartushelp/15.0/mergedProjects/hdl/vlog/vlog_pro_ram_inferred.htm
infer 一个双口ram的代码如下




  1. module ram_dual(q, addr_in, addr_out, d, we, clk1, clk2);
  2.    output[7:0] q;
  3.    input [7:0] d;
  4.    input [6:0] addr_in;
  5.    input [6:0] addr_out;
  6.    input we, clk1, clk2;

  7.    reg [6:0] addr_out_reg;
  8.    reg [7:0] q;
  9.    reg [7:0] mem [127:0];

  10.    always @(posedge clk1) begin
  11.       if (we)
  12.          mem[addr_in] <= d;
  13.    end

  14.    always @(posedge clk2) begin
  15.       q <= mem[addr_out_reg];
  16.       addr_out_reg <= addr_out;
  17.    end
  18.         
  19. endmodule


复制代码


在quartus和ISE中看的RTL视图是一样的
F75`ED{V7$N@BZH4VW`I)FN.png

在ISE中的technology schematic是这样的
W9M@U[5T2]2_]IIS77W$)NK.png

郁闷了,您在ISE中能综合出双口RAM吗?

没有使用例化IP的方法是因为修改位宽和深度很麻烦,现在不急用就攒攒经验,到用的时候方便
发表于 2018-10-15 21:46:36 | 显示全部楼层
你看得这个网页里给出的是simple dual port的例子,
The example below shows ram_dual.v, a Verilog Design File that implements a 128 x 8-bit simple dual-port RAM with separate read and write clocks.

你需要的是true dual port,
重新再找找
 楼主| 发表于 2018-10-16 10:56:07 | 显示全部楼层
回复 6# gooseman





  1. module true_dual_port_ram_dual_clock
  2. #(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
  3. (
  4.         input [(DATA_WIDTH-1):0] data_a, data_b,
  5.         input [(ADDR_WIDTH-1):0] addr_a, addr_b,
  6.         input we_a, we_b, clk_a, clk_b,
  7.         output reg [(DATA_WIDTH-1):0] q_a, q_b
  8. );

  9.         // Declare the RAM variable
  10.         reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];

  11.         always @ (posedge clk_a)
  12.         begin
  13.                 // Port A
  14.                 if (we_a)
  15.                 begin
  16.                         ram[addr_a] <= data_a;
  17.                         q_a <= data_a;
  18.                 end
  19.                 else
  20.                 begin
  21.                         q_a <= ram[addr_a];
  22.                 end
  23.         end

  24.         always @ (posedge clk_b)
  25.         begin
  26.                 // Port B
  27.                 if (we_b)
  28.                 begin
  29.                         ram[addr_b] <= data_b;
  30.                         q_b <= data_b;
  31.                 end
  32.                 else
  33.                 begin
  34.                         q_b <= ram[addr_b];
  35.                 end
  36.         end

  37. endmodule


复制代码

i find this in quartus templates,
RTL viewer:
RWH3YDAO_MVUR}PPQVXY$KD.png
and technology map viewer :
RMP0LCPU@_26PZNHMVSZX0Y.png
thx very much
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条


小黑屋| 手机版| 关于我们| 联系我们| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-12-27 20:17 , Processed in 0.020747 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表