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

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

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 4832|回复: 14

[求助] 请教关于SRAM(VHDL)建模的一些问题

[复制链接]
发表于 2012-7-27 13:23:40 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 jefby 于 2012-7-27 16:20 编辑

最近在研究SRAM,然后自己写个Vhdl程序来验证设计的SRAM模型是否正确。结果代码中存在一些问题:无语法错误,但是读取数据时不能有效读出。废话不多说。模型代码如下:



  1. library IEEE;
  2. use IEEE.STD_LOGIC_1164.ALL;
  3. use IEEE.STD_LOGIC_ARITH.ALL;
  4. use IEEE.STD_LOGIC_UNSIGNED.ALL;

  5. entity sram is
  6.   port(
  7.                 sram_addr : in STD_LOGIC_VECTOR(3 DOWNTO 0);--地址信号
  8.                   sram_oe : in STD_LOGIC;--输出允许信号
  9.                   sram_we : in STD_LOGIC;--写允许信号
  10.                 sram_data : inout STD_LOGIC_VECTOR(7 DOWNTO 0);--读取到的数据或者写入的数据
  11.                   sram_ce : in STD_LOGIC--芯片有效信号
  12.       );
  13. end sram;

  14. architecture Behavioral of sram is

  15. TYPE memory_array IS ARRAY ( 0 TO 15 )OF STD_LOGIC_VECTOR(7 DOWNTO 0);

  16. SIGNAL mysram : memory_array;--定义16*8bit SRAM

  17. SIGNAL int_addr : INTEGER  RANGE 0 TO 15;
  18. SIGNAL we_rise,din_change :TIME :=  0 ns;

  19. begin
  20. int_addr <= CONV_INTEGER(sram_addr);--将位矢量转换为int型数据

  21. PROCESS(sram_we)
  22. BEGIN
  23.    IF(sram_we'EVENT AND sram_we = '1') THEN --当we上升沿
  24.            IF(sram_ce ='0' AND sram_we ='1') THEN --检测片选是否有效,且sram_we是否为高电平,若是,则更新数据
  25.                mysram(int_addr) <= sram_data AFTER 2 ns;
  26.            END IF;
  27.    END IF;--   IF(sram_we'EVENT AND sram_we = '1')
  28.    we_rise <= NOW;
  29.    ASSERT (NOW - din_change >= 2 ns);
  30.    REPORT "SETUP ERROR din(SRAM)"
  31.    SEVERITY WARNING; --din 建立时间检查
  32. END PROCESS;

  33. PROCESS(sram_oe,sram_ce)
  34. BEGIN
  35.         IF(sram_oe = '0' AND sram_ce ='0') THEN
  36.                 sram_data <= mysram(int_addr) AFTER 3 ns;
  37.         ELSE
  38.                 sram_data <= "ZZZZZZZZ" AFTER 4 ns;
  39.         END IF;
  40. END PROCESS;



复制代码

测试文件如下所示:




  1. LIBRARY IEEE;
  2. USE IEEE.STD_LOGIC_1164.ALL;


  3. ENTITY sram_test IS
  4. END sram_test;

  5. ARCHITECTURE behav OF sram_test IS
  6.         COMPONENT sram
  7.                 PORT
  8.                 (
  9.                         sram_addr:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
  10.                       sram_oe  :IN STD_LOGIC;
  11.                       sram_we  :IN STD_LOGIC;
  12.                       sram_data  :INOUT STD_LOGIC_VECTOR(7 DOWNTO 0);
  13.                         sram_ce  :IN STD_LOGIC
  14.                 );
  15.         END COMPONENT;

  16. SIGNAL addr:STD_LOGIC_VECTOR (3 DOWNTO 0);
  17. SIGNAL  oe:STD_LOGIC;
  18. SIGNAL  we:STD_LOGIC;
  19. SIGNAL io:STD_LOGIC_VECTOR(7 DOWNTO 0);
  20. SIGNAL ce:STD_LOGIC;

  21. BEGIN
  22.         uut:sram PORT MAP
  23.                          (
  24.                             sram_addr => addr,
  25.                             sram_oe   => oe,
  26.                             sram_we   => we,
  27.                             sram_data   => io,
  28.                             sram_ce   => ce
  29.                          );
  30.         PROCESS
  31.           BEGIN
  32.                 addr <= "0000";
  33.                   io <= "00000001";
  34.                   wait for 2 ns;
  35.                   oe <= '1';
  36.                   we <= '1';
  37.                   ce <= '0';
  38.                   wait for 2 ns;
  39.                   we <= '0';
  40.                   wait for 8 ns;
  41.                   we <= '1';
  42.                   wait for 4 ns; --第一个上升沿
  43.                   addr <= "0001";
  44.                   io <= "00000010";
  45.                   wait for 2 ns;
  46.                   we <= '0';
  47.                   wait for 8 ns; --第二个上升沿
  48.                   we <= '1';
  49.                   wait for 2 ns;
  50.                   addr <= "0000";
  51.                   wait for 2 ns;
  52.                   oe <= '0';
  53.                   wait for 8 ns;
  54.                   oe <= '1';
  55.                   addr <= "0001";
  56.                   wait for 2 ns;
  57.                   oe <= '0';
  58.                   wait for 8 ns;
  59.                   oe <= '1';
  60.                   wait;
  61.         END PROCESS;

  62. END behav;


复制代码



仿真截图如下所示:
sram_仿真错误图.png

当sram_oe为低电平,地址sram_addr为"0000"时,此时应该端口sram_data应该读出数据"00000001"但是仿真图上显示为"000000xx",请高手指点!!
发表于 2012-7-27 17:06:19 | 显示全部楼层
你看数据是000000xx,也就是说高多少位都是确定数据,低多少位是不确定数据,而之前看到数据已经为00001过,说明原始数据也是确定的。

你查一下,是不是之前在地址为0时有个写使能写进去了数据,而这个数据刚好后面为XX,不小心把不要的数据写进去了一小半。
 楼主| 发表于 2012-7-27 19:49:04 | 显示全部楼层
回复 2# eaglelsb
好像不是这个问题,并没有写入新的数据;应该是inout类型的问题吧,我重新修改了代码,在输出时重新定义了一个数据端口dout,这样读出的数据便是正确的;但我不知道怎么改。求进一步指导。修改的代码如下




  1. PROCESS(sram_oe,sram_ce)
  2. BEGIN
  3.         IF(sram_oe = '0' AND sram_ce ='0') THEN
  4.                 dout <= mysram(int_addr) ;
  5.         ELSE
  6.                 dout <= "ZZZZZZZZ" ;
  7.         END IF;
  8. END PROCESS;

  9. sram_data <= dout WHEN  sram_ce ='0'  ELSE
  10.              "ZZZZZZZZ";


复制代码
发表于 2012-7-28 01:02:56 | 显示全部楼层
反复看了几遍,终于看明白了,we是高有效,ce与oe是低有效,同时你还用组合逻辑使用了after 2ns之类的延迟。
你看出问题的地方附近,oe为0与we为1同时存在,表明这端口同时在读与写,这是不应该存在的啊?

另外,如果你最终是为了综合到CPLD中使用,那最好不要用after 2ns之类的语句,因为综合是无效的,同时会使仿真结果与上板结果不一致。 并且你一会用 after 2 ns, 一会3ns,这也最好不使用。建设统一不用,有相关需求都做在TB中,可综合的代码归综合,仿真的归仿真。
你关于双向数据的处理没有问题,输入时直接进来,输出时通过使能进行三向选择,这是标准做法。
 楼主| 发表于 2012-7-28 10:27:40 | 显示全部楼层
本帖最后由 jefby 于 2012-7-28 10:29 编辑

回复 4# eaglelsb


   你好,按照你说的问题改了,可是还是还存在那个问题,您能不能再帮忙修改下,谢谢!!
发表于 2012-7-28 11:24:48 | 显示全部楼层
回复 5# jefby


   你再贴波形出来看看,
发表于 2012-7-28 11:27:16 | 显示全部楼层
另外,真的没有时钟吗?必须用全组合逻辑去完成?这个倒觉得关系不大。
你贴波形时,如果还有XX的,把相关部分的细节也贴出来看看
 楼主| 发表于 2012-7-28 12:19:57 | 显示全部楼层
回复 7# eaglelsb

现在的仿真波形图: sram_仿真错误图.png
   图中黄色椭圆所画部分为我难以理解的地方,此时应该为“ZZZZZZZZ"的,但是输出却为”00000002“,在下降沿读出数据可以读到端口data_o上,但是当赋值给sram_data时,数据还是错误。很不理解。详细程序如下





  1. begin
  2.         int_addr <= CONV_INTEGER(sram_addr);
  3.         data_i <= sram_data WHEN dir = '0' ELSE (OTHERS => 'Z'); --当dir='0'用作输入,dir='1'用作输出

  4.         write_data:PROCESS(sram_we)
  5.         BEGIN
  6.                 IF(sram_we'EVENT AND sram_we ='1') THEN--上升沿写入数据
  7.                         IF(sram_ce ='1' AND dir = '0') THEN
  8.                          mysram(int_addr) <= data_i;
  9.                               END IF;
  10.                 END IF;
  11.         END PROCESS write_data;
  12.         read_data:PROCESS(sram_oe)
  13.         BEGIN
  14.                 IF(sram_oe'EVENT AND sram_oe ='0') THEN --下降沿读数据到端口data_o
  15.                         IF(sram_ce ='1' AND dir ='1') THEN
  16.                                 data_o <= mysram(int_addr);
  17.                         ELSE
  18.                                 data_o <= (OTHERS => 'Z');
  19.                         END IF;
  20.                 END IF;
  21.         END PROCESS read_data;

  22.      PROCESS(data_o,dir,sram_ce,sram_oe) --
  23.      BEGIN
  24.              IF(dir = '1' AND sram_ce ='1' AND sram_oe ='0') THEN
  25.                      sram_data <= data_o ;
  26.              ELSE
  27.                      sram_data <= (OTHERS => 'Z');
  28.              END IF;
  29.      END PROCESS;

  30. end Behavioral;


复制代码
发表于 2012-7-28 12:23:33 | 显示全部楼层
如果你能使用同步时钟最好,如果不能,还是要注意下异步信息的处理。
就是读写时,当你要切换到再一个地址时,先把读写使能关上,再跳到下一个地址,然后读写,结束后再关掉使能,再跳到下一个地址。这样做才能避免误写误读。

比如一个SRAM模型是相当简单的,你再弄异步的话,就做复杂了。 现在仿真出问题还算不了啥,上板实测出问题才纠结呢
发表于 2012-7-28 12:31:11 | 显示全部楼层
兄弟写的代码风格
IF(sram_oe'EVENT AND sram_oe ='0') THEN --下降沿读数据到端口data_o

16.                        IF(sram_ce ='1' AND dir ='1') THEN

这个的意思是把sram_oe作为时钟信息来采集下降沿来取数据,
还有段是把sram_we作为时钟来采集上升沿的数据,

一半组合逻辑,一半时钟逻辑,

你先别纠结结果为啥错了,先引进个时钟来完全重新来写段同步代码吧,
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

×

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

GMT+8, 2024-5-13 13:10 , Processed in 0.039517 second(s), 10 queries , Gzip On, Redis On.

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