我正在尝试在斯巴达6上编写类似i2c的总线。我有一堆状态,我在使用下面的计数器。
-- Timer --
TimesUp <= true when TmrCnt = 0 else
false when TmrCnt /= 0 else
false;
tmrProc: process(ClkxC, SetTmr, TmrInit)
begin
if (rising_edge(ClkxC)) then
if (SetTmr = '1') then
TmrCnt <= TmrInit;
elsif (TmrCnt > 0) then
TmrCnt <= TmrCnt - 1;
end if;
end if;
end process;
问题是我的状态机是在同一个时钟上运行的,并且对于一些短时间的状态,它只会爆炸,好像定时器没有及时设置。
所以我尝试了这个:
-- Timer --
TimesUp <= true when TmrCnt = 0 else
false when TmrCnt /= 0 else
false;
tmrProc: process(ClkxC, SetTmr, TmrInit)
begin
if (SetTmr = '1') then
TmrCnt <= TmrInit;
elsif (rising_edge(ClkxC)) then
if (TmrCnt > 0) then
TmrCnt <= TmrCnt - 1;
end if;
end if;
end process;
现在它模拟得很好,但是当我尝试实现时,我收到一条错误消息:
This design contains one or more registers/latches that are directly incompatible with the Spartan6 architecture. The two primary causes of this is either a register or latch described with both an asynchronous set and asynchronous reset, or a register or latch described with an asynchronous set or reset which however has an initialization value of the opposite polarity (i.e. asynchronous reset with an initialization value of 1).
我真的不知道如何在不制动斯巴达规则6的情况下让定时器加载足够快。
答案 0 :(得分:2)
警告已在Xilinx WP309 Targeting and Retargeting Guide for Spartan-6 FPGAs [P9-11]中明确说明。
To reduce cost of the overall architecture, slices in Spartan-6 FPGAs do not have a REV
pin. As a result, flip-flops no longer implement both a set signal and a reset signal. In
addition, a register with a set or reset signal can only have an initialization value of
the same polarity. For example, a flip-flop with an asynchronous reset can only have an
initialization value of 0.
也就是说,使用Xilinx Spartan-6 FPGA时,以下类型的寄存器/锁存器 NOT RECOMMENDED :
______|______
| Set |
| |
---| D Q |--- -- 1. a register/latch with both ASYNCHRONOUS
| _ | set and reset signals
---|>Clk Q |o-- -- NOT RECOMMENDED
| |
| Reset |
|___________|
|
-- 2. a register/latch described with an ASYNCHRONOUS set/reset which
however has an initialization value of the opposite polarity
-- The default value of reg is 0 which is the left
-- bound value of the integer type definition.
signal reg: integer range 0 to 7; <-----
|
process (clk, reset) |___ opposite
begin | NOT RECOMMENDED
if (reset = '0') then |
reg <= 7; <-----
elsif ( rising_edge(clk) ) then
reg <= val;
end if;
end process;
Xilinx推荐的解决方案:
1. Remove either the set or reset from all registers and latches
if not needed for required functionality
2. Modify the code in order to produce a synchronous set and/or
reset (both is preferred)
3. Ensure all registers have the same initialization value as the
described asynchronous set or reset polarity
4. Use the -async_to_sync option to transform the asynchronous
set/reset to synchronous operation
(timing simulation highly recommended when using this option)
在您的设计中,您可以将TmrCnt
初始化为TmrInit
或向上计数TmrCnt
。
答案 1 :(得分:2)
从第一种(同步)方法转向第二种(异步集)很少是解决问题的正确方法;无论Spartan-6经济体的重置逻辑如何。事实上,我会以......“不要那样做”为理由来证明这一点。
相反,请查看语句“问题是我的状态机是在同一个时钟上运行的,并且对于一些短时间的状态它只会爆炸,好像定时器没有及时设置。”
首先,I2C信号没有短暂的持续时间,除非这可能是它的数百MHz导数......
其次,VHDL做的事情非常好是同步设计,因此“爆破”而不将计数器点重置为其他东西:可能信号分配规则引用here。 / p>
我怀疑这会导致状态机设置SetTmr
以在单独的进程中与计数器通信的问题;所以计数器在一个循环后看到SetTmr
,并且该循环延迟导致观察到的错误行为,因为在该循环期间TimesUp具有错误的值。
一个答案 - 我经常使用的模式 - 只是将计时器滚动到SM过程本身;然后你直接设置并保存握手逻辑和一个单独的过程...
StateMch : process(Clock)
begin
if rising_edge(Clock) then
-- default actions
if Timer > 0 then
Timer <= Timer - 1;
end if;
-- state machine
case State is
when Start_Wait =>
Timer <= My_Delay;
State <= Waiting;
when Waiting =>
if Timer = 0 then
State <= Done;
end if;
when others =>
State <= Start_Wait;
end case;
end if;
end process;
除了比大量微小进程更简单和(我发现)更容易理解之外,这允许几个州使用相同的计时器来产生不同的延迟。