我有一个非常简单的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的评论!
3 回答
我会支持马丁 .
将双向性保持在顶层,然后将下面的所有逻辑看作两条总线,一条输入总线和一条输出总线 .
输入总线始终与双向数据总线相同 .
然后,当输出有效时,双向数据总线被分配输出总线,当无效时,Z被分配给输出总线 .
Z将被总线的实际输入状态覆盖 .
此外,当您确实需要变量赋值
:=
时,您使用了几次信号分配符号<=
.所以,你想写
用于将值
a
赋值给变量v
的字段,和将
a
分配给信号或端口s
.使用
inout
s最好将其在顶层分成两个信号data_from_outside
和data_to_outside
. 然后你的下层需要实体上的三个元素,一个输入向量,一个输出向量和一个信号来说明何时驱动外部数据 . 双向信号也不适合记录 .最高级别需要做:
从风格的角度来看:把一切都放在一个过程中 . 关于这一点有一些争论,但comp.arch.fpga和comp.lang.vhdl上的许多受人尊敬的海报都是这种观点 .