我想知道逻辑合成器如何解释条件复位值。 例如,FSM的初始状态取决于异步复位信号和其他一些信号,如下所示。
state_reg : process(clk, reset)
begin
if reset = '0' then
if cond = '1' then
state <= init_state_0;
else
state <= init_state_1;
end if;
elsif rising_edge(clk) then
state <= next_state;
end if;
end process;
我知道当复位值是一个常数时,某些寄存器优化是由合成器执行的,但是在上述示例中,情况也是这样吗?
之所以这样设计是因为状态机的优化,因为不需要在两个初始状态之间进行选择就可以选择中间状态。
答案 0 :(得分:1)
我写了Verilog。
我曾经修改过一个实现条件重置值的行业代码。
assign ctrl_rst_n = sw_rst_n | cond;
assign ctrl_set_n = sw_rst_n | ~cond;
always@(posedge clk or negedge ctrl_rst_n or negedge ctrl_set_n)begin
if(~ctrl_rst_n)begin
ctrl <= 1'b0;
end else if(~ctrl_set_n)begin
ctrl <= 1'b1;
end else begin
(... normal function logic ...)
end
end
综合后,我得到了以下网表:
ctrl_rst_n ---+
___v___
| clr |
|D Q|
|CK |
|__set__|
^
ctrl_set_n ---+
在外部模块中有两个名为sw_rst_n
和cond
的用户寄存器,可以通过软件访问。
编程指南如下:
用户设置或清除cond
寄存器以配置信号ctrl
的重置值;
然后清除sw_rst_n
寄存器,然后进行设置操作以发出软件复位(软件复位不会复位用户寄存器块);
软件重置后,信号ctrl
从所需的重置值开始。
答案 1 :(得分:0)
我不确定我们是否可以考虑对这个小代码示例进行优化
因此,考虑到COND的两次采样将花费2个时钟周期,我们可以在3个时钟周期后取消声明内部复位,从而利用这些约束条件来拟定某种适当的(imho)复位状态。
通过这种方式,我们可以受益于(几乎)一个时钟周期的稳定复位状态。
但是可以肯定的是,您可以在FPGA上执行此操作,在FPGA上您可以将数据信号(此处是内部复位,而不是外部RESET_N)导出到“时钟”分配“网格”。
下面提供了代码以供参考,您可以在EDA Playground下找到它
library IEEE;
use IEEE.std_logic_1164.all;
entity state_machine is
port ( CLOCK : in std_logic;
RESET_N : in std_logic;
COND : in std_logic;
OUTPUT : out std_logic_vector(7 downto 0));
end entity;
architecture rtl of state_machine is
type state_type is ( S1, S2, S3, S4);
signal state, next_state : state_type;
signal reset_state : state_type;
constant RSYNC_LENGTH : natural := 3;
signal reset : std_logic;
signal reset_v : std_logic_vector(RSYNC_LENGTH-1 downto 0);
signal scond : std_logic;
signal scond_q1 : std_logic;
signal outbuf : std_logic_vector(7 downto 0);
begin
reset_sync: process(CLOCK,RESET_N)
begin
if RESET_N = '0' then
reset_v <= (others => '1');
elsif rising_edge(CLOCK) then
reset_v(0) <= '0';
reset_v(RSYNC_LENGTH-1 downto 1) <= reset_v(RSYNC_LENGTH-2 downto 0);
end if;
end process reset_sync;
reset <= reset_v(RSYNC_LENGTH-1);
sync: process(CLOCK,RESET_N)
begin
if RESET_N = '0' then
scond <= '0';
scond_q1 <= '0';
elsif rising_edge(CLOCK) then
scond_q1 <= COND;
scond <= scond_q1;
end if;
end process sync;
reset_state <= S2 when scond='1' else S1;
SM : process(CLOCK,reset)
begin
if reset = '1' then
state <= reset_state;
elsif ( rising_edge(CLOCK) ) then
state <= next_state;
end if;
end process SM;
statedecoder: process(state)
begin
case ( state ) is
when S1 => next_state <= S2;
outbuf <= x"01";
when S2 => next_state <= S3;
outbuf <= x"02";
when S3 => next_state <= S4;
outbuf <= x"03";
when S4 => next_state <= S1;
outbuf <= x"04";
when others =>
next_state <= S1;
outbuf <= x"00";
end case;
end process statedecoder;
OUTPUT <= outbuf when reset = '0' else x"00";
end architecture rtl;