在SOPC下面挂了一个I2C Slave的外设,用了几天之后发现经常会发生I2C Slave的状态机死锁,发生时间在几天到几周,想到了用Virtual JTAG来观察状态机的跳转以及其他寄存器在死锁之后的值,问题就是,RTL描述采用VHDL,其状态机的状态值用枚举变量描述,无法对应到确定位宽的逻辑向量,查阅了一些VHDL书籍之后,可以用下述方法把枚举值转化到逻辑向量,不需要将原先的枚举值换成常量值:
type state is (one, two, three);
signal cursts : state;
signal stsout1: std_logic_vector(2 downto 0);
type sts2slv is array(state) of std_logic_vector(2 downto 0);
constant val_sts2slv : sts2slv := (
"001", -- one
"010", -- two
"100"); -- three
下面的进程将cursts的当前状态转换至std_logic_vector(2 downto 0):
process (clk, rst)
begin -- process
if rst = '1' then -- asynchronous reset (active high)
stsout1 <= (others => '0');
elsif rising_edge(clk) then
stsout1 <= val_sts2slv(cursts);
end if;
end process;
RTL Viewer如下:
QuartusII的综合结果描述如下:
1、 综合器为状态机cursts选定状态编码,可以是001,010,100,也可以不是;
2、 状态编码值到val_sts2slv的组合逻辑转换;
3、 锁存输出;
利用上面的做法,将状态值转换到确定的逻辑向量,不需要更改原先State枚举类型定义,当我们不需要监视状态时,直接将上述代码注释掉即可,较为灵活。