这个程序只有一个问题,就是在
if reset = '1' then
cnt := 0;
这里没有加上复位状态 led <= '1';
简单的逻辑里面,这样的做法让人觉得很奇怪,但是多数复杂的逻辑状态下,这却是省资源和提高速度的做法,作以下假设:正常的逻辑过程如下
if a='1' and b='1' then
if c='1' and d='1' then
led <= '1';
aaaa<="0000";
else
led <= '0';
aaaa<=aaaa;
end if;
else
aaaa<="1111";
led <= '0';
end if;
这相当于两个逻辑过程扯到了一起,对aaaa和led进行条件幅值,对这样一个问题有很多种不同的做法,我可以举出以下句法:
led<=a and b and c and d;一句话搞定,简洁明了,当a,b,c,d为单比特时好办,如果为向量,就麻烦了。
当条件变得复杂时,不能用上面的逻辑表达式,好,换一种
led <= '0';
if a='1' and b='1' and c='1' and d='1' then
led <= '1';
end if;
这句话同样没有else led <= '0';,把led <= '0';放到上面去了,好,再来理解这句话
默认情况下led <= '0';当满足条件时再赋值1,编译器最终会编译成FDS port map(C=>clk,D=>'0',S=>SSS,...),SSS就是上面的条件最后综合出来的一个信号。
当你对寄存器进行操作时,FPGA的FF隐含了几种逻辑,这种逻辑是不需要你用代码描述出来的。
理解这些逻辑很重要,可以写出简洁,可靠的代码。
if a='0' or b='0' then
aaaa<="1111";
elsif c='1' and d='1' then
aaaa<="0000";
end if;不需要else了,else是隐性的,这几行逻辑实现的就是FDRSE,隐性的else就是CE='0'的情况,寄存器的值保持不变。
条件赋值,可以综合成前面根据条件来实现MUX,最后加上一级FD锁存,也可以把诸多条件直接加到FDRSE上,省去大量的逻辑。FDRSE是FPGA的一个精髓
FDRSE_inst : FDRSE
generic map (
INIT => '0') -- Initial value of register ('0' or '1')
port map (
Q => Q, -- Data output
C => C, -- Clock input
CE => CE, -- Clock enable input
D => D, -- Data input
R => R, -- Synchronous reset input
S => S -- Synchronous set input
);
这实现的是什么功能呢,
if C'event and C='1' then
if R='1' then
Q<='0';
elsif S='1' then
Q<='1';
elsif CE='1' then
Q<=D;
else
Q<=Q;
end if;
end if;
这个一个原生的FF是不是保护了强大的条件赋值功能,而这是不需要你额外花逻辑去实现的。
在你设计逻辑的时候,只要不违反语法,只要不违反设计细想,只要便于阅读,都是可以的。
楼主那个问题,我的做法是这样的
process (clk)
variable cnt : std_logic_vector(0 to 2);
begin
if clk'event and clk='1' then
if reset = '1' then
cnt := (others=>'0');
led<='1';
else
cnt := cnt + 1;
led<=cnt(0) or cnt(1) or cnt(2) ;
end if;
end if;
end process;
假设cnt非常大,则变成
process (clk)
variable cnt : std_logic_vector(0 to 31);
begin
if clk'event and clk='1' then
if reset = '1' then
cnt := (others=>'0');
led<='1';
else
cnt := cnt + 1;
led<='1';
if cnt=0 then
led<='0';
end if;
end if;
end if;
end process;
led赋0值只有一种情况,cnt=0的时候,其它情况都赋1值
led<='1';
if cnt=0 then
led<='0';
end if;
和
if cnt=0 then
led<='0';
else
led<='1';
end if;
意义和编译之后的结果是一模一样的,不会存在任何问题,你对VHDL的基本原则理解了就会认同我的观点。尽信书不如无书。
还有一个问题,各位发现了没有,我定义了一个std_logic_vector(0 to 31);是不是非常不顺眼?
向量为什么要这样定义,不规范啊,这个规范的基本原则是什么?是某本书上说的吗,有道理吗?
我有我的道理,我们的powerpc,microblaze都是big endian的,这样描述对于字节的寻址会减少非常多的不必要的麻烦。
另外,网络通信,SPI,I2C通信采用这种方式会减少BYTE之间的交换,避免引起混淆。
当然书上讲的都是std_logic_vector(31 downto 0);这些都是都不是死的,以简洁实用为主,各自好好理解吧。
|