我有一个非常简单的FSM,它应该驱动一些外部RAM的输出信号。我遇到的问题是处理数据总线 这可以输入也可以输出...我不太清楚如何处理 在我的FSM中最好这种情况。问题来自以下几行:
v.sram_data <= io_sram_data;
显然,左手侧是变量,而右手侧是信号。有一种“好的”方法如何处理FSM中的inout信号,就像我拥有的那样?
entity sram_fsm is
port (
clk : in std_logic;
reset : in std_logic;
out_sram_rd : out std_logic;
out_sram_wr : out std_logic;
out_sram_addr : out std_logic_vector(3 downto 0);
io_sram_data : inout std_logic_vector(7 downto 0)
);
end;
architecture Behavioral of sram_fsm is
type state_type is (wr_init, wr_data, rd_init, rd_data);
type reg_type is record
state : state_type;
sram_data : std_logic_vector(7 downto 0);
sram_addr : std_logic_vector(3 downto 0);
sram_rd : std_logic;
sram_wr : std_logic;
end record;
signal r, rin : reg_type;
begin
comb : process (r)
variable v : reg_type;
begin
v := r;
case r.state is
when wr_init =>
v.sram_data := "00000000";
v.sram_addr := "0000";
v.sram_rd := '0';
v.sram_wr := '0';
v.state := wr_data;
when wr_data =>
io_sram_data <= "00001000";
v.sram_wr := '1';
v.state := rd_init;
when rd_init =>
v.sram_addr := "0000";
v.sram_rd := '1';
v.sram_wr := '0';
v.state := wr_data;
when rd_data =>
v.sram_data <= io_sram_data;
v.state := wr_init;
end case;
out_sram_addr <= v.sram_addr;
out_sram_rd <= v.sram_rd;
out_sram_wr <= v.sram_wr;
rin <= v;
end process;
regs : process (reset, clk)
begin
if reset = '0' then
r.state <= wr_init;
elsif rising_edge(clk) then
r <= rin;
end if;
end process;
end Behavioral;
非常感谢代码改进这个简单的FSM的评论!
答案 0 :(得分:2)
使用inout
s最好将其从顶层拆分为两个信号data_from_outside
和data_to_outside
。然后你的下层需要实体上的三个元素,一个输入向量,一个输出向量和一个信号来说明何时驱动外部数据。双向信号也不适合记录。
最高级别需要做:
data_pins <= data_to_outside when data_to_outside_enable = '1' else (others => 'Z');
data_from_outside <= data_pins;
从风格的角度来看:把所有东西都放在一个过程中。关于这一点有一些争论,但comp.arch.fpga和comp.lang.vhdl上的许多受人尊敬的海报都是这种观点。
答案 1 :(得分:1)
此外,当您确实需要变量赋值<=
时,您曾多次使用信号分配符号:=
。
所以,你想写
v.f := a;
用于将值a
分配给变量v
的字段,以及
s <= a;
将a
分配给信号或端口s
。
答案 2 :(得分:0)
我会支持马丁。
将双向性保留在顶层,然后将下面的所有逻辑看作两条总线,一条输入总线和一条输出总线。
输入总线始终与双向数据总线相同。
双向数据总线在输出有效时分配输出总线,在无效时分配给Z.
Z将被总线的实际输入状态覆盖。