无法为 VHDL 中的整数信号赋值
Can't assign value to integer signal in VHDL
我正在使用可编程逻辑根据摩尔斯电码将一系列长脉冲或短脉冲解码为拉丁字母。我使用 VHDL 来描述我们的设计,准确地说,我使用 Quartus Prime 进行设计,使用 ModelSim 进行仿真。我的 CPLD 是 ALTERA MAX-V 5M160ZE64C5.
这是我的代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all ;
use ieee.std_logic_arith.all;
entity SauvezLesMorses is
port
(
-- Input ports
clk : in std_logic;
message : in std_logic;
display : in std_logic;
start : in std_logic;
-- Output ports
seg14 : out std_logic_vector (13 downto 0);
lengthLED : out std_logic := '0'
);
end entity SauvezLesMorses;
architecture SauvezLesMorses_arch of SauvezLesMorses is
type state_t is (A, B, C);
signal state : state_t;
signal count : integer range 0 to 4 := 0;
signal clk_cnt : integer range 0 to 21 := 0;
signal morse : std_logic_vector (3 downto 0);
begin
process (clk, start)
variable vectorDummy : std_logic_vector (3 downto 0);
begin
if (start = '1') then
state <= A;
count <= 0;
seg14 <= "00000010001000";
morse <= "0000";
lengthLED <= '0';
elsif (rising_edge(clk)) then
case state is
-- Idle, listening
when A =>
if (display = '0') then
if (message = '1' and count < 4) then
state <= B;
seg14 <= "00000010001000";
count <= count;
morse <= morse;
lengthLED <= '0';
clk_cnt <= 0;
else
state <= A;
seg14 <= "00000010001000";
count <= count;
morse <= morse;
lengthLED <= '0';
end if;
else
state <= C;
count <= count;
morse <= morse;
lengthLED <= '0';
seg14 <= "00000010001000";
end if;
-- Measuring impulse length
when B =>
if (display = '0') then
if (message = '1') then
state <= B;
count <= count;
morse <= morse;
seg14 <= "00000010001000";
if (clk_cnt < 20) then
clk_cnt <= (1 + clk_cnt);
lengthLED <= '0';
else
clk_cnt <= 21;
lengthLED <= '1';
end if;
else
state <= A;
if (clk_cnt < 21) then
morse <= morse;
else
case count is
when 0 => vectorDummy := "1000";
when 1 => vectorDummy := "0100";
when 2 => vectorDummy := "0010";
when 3 => vectorDummy := "0001";
when others => vectorDummy := "0000";
end case;
morse <= morse or vectorDummy;
end if;
count <= count + 1;
lengthLED <= '0';
seg14 <= "00000010001000";
end if;
else
state <= C;
count <= count;
morse <= morse;
lengthLED <= '0';
seg14 <= "00000010001000";
end if;
-- Displaying converted character to user
when C =>
if (display = '0') then
state <= A;
count <= 0;
seg14 <= "00000010001000";
lengthLED <= '0';
morse <= "0000";
else
state <= C;
count <= count;
morse <= morse;
lengthLED <= '0';
if(count = 1) then
case morse is
when "0000" => seg14 <= "10011110001000"; --E
when "1000" => seg14 <= "10000000100010"; --T
when others => seg14 <= "11111111111111"; --unknown character
end case;
elsif(count = 2) then
case morse is
when "0100" => seg14 <= "11101110001000"; --A
when "1000" => seg14 <= "01101101000100"; --N
when "1100" => seg14 <= "01101101010000"; --M
when "0000" => seg14 <= "00000000100010"; --I
when others => seg14 <= "11111111111111"; --unknown character
end case;
elsif(count = 3) then
case morse is
when "0000" => seg14 <= "10110110001000"; --S
when "0010" => seg14 <= "01111100000000"; --U
when "0100" => seg14 <= "11001110001100"; --R
when "0110" => seg14 <= "01101100000101"; --W
when "1000" => seg14 <= "11110000100010"; --D
when "1010" => seg14 <= "00001110010100"; --K
when "1100" => seg14 <= "10111100001000"; --G
when "1110" => seg14 <= "11111100000000"; --O
when others => seg14 <= "11111111111111"; --unknown character
end case;
elsif(count = 4) then
case morse is
when "0000" => seg14 <= "01101110001000"; --H
when "0001" => seg14 <= "00001100010001"; --V
when "0010" => seg14 <= "10001110001000"; --F
when "0100" => seg14 <= "00011100000000"; --L
when "0110" => seg14 <= "11001110001000"; --P
when "0111" => seg14 <= "01111000000000"; --J
when "1000" => seg14 <= "11110000101010"; --B
when "1001" => seg14 <= "00000001010101"; --X
when "1010" => seg14 <= "10011100000000"; --C
when "1011" => seg14 <= "00000001010010"; --Y
when "1100" => seg14 <= "10010000010001"; --Z
when "1101" => seg14 <= "11111100000100"; --Q
when others => seg14 <= "11111111111111"; --unknown character
end case;
else
seg14 <= "11111111111111";
end if ;
end if;
end case;
end if;
end process;
end architecture SauvezLesMorses_arch ;
带参数的modelsim仿真
force -freeze sim:/sauvezlesmorses/clk 1 0, 0 {25000000000 ps} -r {50 ms}
force -freeze sim:/sauvezlesmorses/display 0 0, 1 {9000000000000 ps} -r {18 sec}
force -freeze sim:/sauvezlesmorses/message 0 0, 1 {3200000000000 ps} -r {6.4 sec}
force -freeze sim:/sauvezlesmorses/start 1 0 -cancel {0.5 sec}
run 40 sec
产生:
Modelsim Simulation
清楚地表明:
clk_cnt
从不增加,而是在 40 秒内保持为零
count
既没有通过激活 start
设置为 0,也没有通过显示的停用设置(即 state
从 C
到 A
).
你知道为什么吗?
P.S。我知道我绝对不是 运行 合适的测试平台。所以即使我应该,也请不要提醒我,除非你知道这是我问题答案的一部分。
强制更新信号值不会生成事件。
参见 IEEE Std 1076-2008 14.7.3.4 信号更新,第 3 段
... If updating a signal causes the current value of that signal to change, then an event is said to have occurred on the signal, unless the update occurs by application of the vhpi_put_value
function with an update mode of vhpiDeposit
or vhpiForce
to an object that represents the signal. ...
可能与 Modelsim 的力或 FLI 使用的机制相同。
有测试台:
library ieee;
use ieee.std_logic_1164.all;
entity slm_tb is
end entity;
architecture foo of slm_tb is
-- Input ports
signal clk: std_logic := '1';
signal message: std_logic := '0';
signal display: std_logic := '0';
signal start: std_logic := '1';
-- Output ports
signal seg14: std_logic_vector (13 downto 0);
signal lengthLED: std_logic;
begin
DUT:
entity work.sauvezlesmorses
port map (
clk => clk,
message => message,
display => display,
start => start,
seg14 => seg14,
lengthLED => lengthLED
);
-- force -freeze sim:/sauvezlesmorses/clk 1 0, 0 {25000000000 ps} -r {50 ms}
-- force -freeze sim:/sauvezlesmorses/display 0 0, 1 {9000000000000 ps} -r {18 sec}
-- force -freeze sim:/sauvezlesmorses/message 0 0, 1 {3200000000000 ps} -r {6.4 sec}
-- force -freeze sim:/sauvezlesmorses/start 1 0 -cancel {0.5 sec}
-- run 40 sec
-- stimulus generators:
CLOCK:
process
begin
wait for 25 ms;
clk <= not clk;
if now > 40 sec then
wait;
end if;
end process;
DISP:
process
begin
wait for 9 sec;
display <= not display;
if now > 35 sec then -- stop simulation at 40 sec
wait;
end if;
end process;
MSG:
process
begin
wait for 3.2 sec;
message <= not message;
if now > 35 sec then
wait;
end if;
end process;
ST:
process
begin
wait for 0.5 sec;
start <= 'U';
wait;
end process;
end architecture;
你确实得到了事件:
我正在使用可编程逻辑根据摩尔斯电码将一系列长脉冲或短脉冲解码为拉丁字母。我使用 VHDL 来描述我们的设计,准确地说,我使用 Quartus Prime 进行设计,使用 ModelSim 进行仿真。我的 CPLD 是 ALTERA MAX-V 5M160ZE64C5.
这是我的代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all ;
use ieee.std_logic_arith.all;
entity SauvezLesMorses is
port
(
-- Input ports
clk : in std_logic;
message : in std_logic;
display : in std_logic;
start : in std_logic;
-- Output ports
seg14 : out std_logic_vector (13 downto 0);
lengthLED : out std_logic := '0'
);
end entity SauvezLesMorses;
architecture SauvezLesMorses_arch of SauvezLesMorses is
type state_t is (A, B, C);
signal state : state_t;
signal count : integer range 0 to 4 := 0;
signal clk_cnt : integer range 0 to 21 := 0;
signal morse : std_logic_vector (3 downto 0);
begin
process (clk, start)
variable vectorDummy : std_logic_vector (3 downto 0);
begin
if (start = '1') then
state <= A;
count <= 0;
seg14 <= "00000010001000";
morse <= "0000";
lengthLED <= '0';
elsif (rising_edge(clk)) then
case state is
-- Idle, listening
when A =>
if (display = '0') then
if (message = '1' and count < 4) then
state <= B;
seg14 <= "00000010001000";
count <= count;
morse <= morse;
lengthLED <= '0';
clk_cnt <= 0;
else
state <= A;
seg14 <= "00000010001000";
count <= count;
morse <= morse;
lengthLED <= '0';
end if;
else
state <= C;
count <= count;
morse <= morse;
lengthLED <= '0';
seg14 <= "00000010001000";
end if;
-- Measuring impulse length
when B =>
if (display = '0') then
if (message = '1') then
state <= B;
count <= count;
morse <= morse;
seg14 <= "00000010001000";
if (clk_cnt < 20) then
clk_cnt <= (1 + clk_cnt);
lengthLED <= '0';
else
clk_cnt <= 21;
lengthLED <= '1';
end if;
else
state <= A;
if (clk_cnt < 21) then
morse <= morse;
else
case count is
when 0 => vectorDummy := "1000";
when 1 => vectorDummy := "0100";
when 2 => vectorDummy := "0010";
when 3 => vectorDummy := "0001";
when others => vectorDummy := "0000";
end case;
morse <= morse or vectorDummy;
end if;
count <= count + 1;
lengthLED <= '0';
seg14 <= "00000010001000";
end if;
else
state <= C;
count <= count;
morse <= morse;
lengthLED <= '0';
seg14 <= "00000010001000";
end if;
-- Displaying converted character to user
when C =>
if (display = '0') then
state <= A;
count <= 0;
seg14 <= "00000010001000";
lengthLED <= '0';
morse <= "0000";
else
state <= C;
count <= count;
morse <= morse;
lengthLED <= '0';
if(count = 1) then
case morse is
when "0000" => seg14 <= "10011110001000"; --E
when "1000" => seg14 <= "10000000100010"; --T
when others => seg14 <= "11111111111111"; --unknown character
end case;
elsif(count = 2) then
case morse is
when "0100" => seg14 <= "11101110001000"; --A
when "1000" => seg14 <= "01101101000100"; --N
when "1100" => seg14 <= "01101101010000"; --M
when "0000" => seg14 <= "00000000100010"; --I
when others => seg14 <= "11111111111111"; --unknown character
end case;
elsif(count = 3) then
case morse is
when "0000" => seg14 <= "10110110001000"; --S
when "0010" => seg14 <= "01111100000000"; --U
when "0100" => seg14 <= "11001110001100"; --R
when "0110" => seg14 <= "01101100000101"; --W
when "1000" => seg14 <= "11110000100010"; --D
when "1010" => seg14 <= "00001110010100"; --K
when "1100" => seg14 <= "10111100001000"; --G
when "1110" => seg14 <= "11111100000000"; --O
when others => seg14 <= "11111111111111"; --unknown character
end case;
elsif(count = 4) then
case morse is
when "0000" => seg14 <= "01101110001000"; --H
when "0001" => seg14 <= "00001100010001"; --V
when "0010" => seg14 <= "10001110001000"; --F
when "0100" => seg14 <= "00011100000000"; --L
when "0110" => seg14 <= "11001110001000"; --P
when "0111" => seg14 <= "01111000000000"; --J
when "1000" => seg14 <= "11110000101010"; --B
when "1001" => seg14 <= "00000001010101"; --X
when "1010" => seg14 <= "10011100000000"; --C
when "1011" => seg14 <= "00000001010010"; --Y
when "1100" => seg14 <= "10010000010001"; --Z
when "1101" => seg14 <= "11111100000100"; --Q
when others => seg14 <= "11111111111111"; --unknown character
end case;
else
seg14 <= "11111111111111";
end if ;
end if;
end case;
end if;
end process;
end architecture SauvezLesMorses_arch ;
带参数的modelsim仿真
force -freeze sim:/sauvezlesmorses/clk 1 0, 0 {25000000000 ps} -r {50 ms}
force -freeze sim:/sauvezlesmorses/display 0 0, 1 {9000000000000 ps} -r {18 sec}
force -freeze sim:/sauvezlesmorses/message 0 0, 1 {3200000000000 ps} -r {6.4 sec}
force -freeze sim:/sauvezlesmorses/start 1 0 -cancel {0.5 sec}
run 40 sec
产生:
Modelsim Simulation
清楚地表明:
clk_cnt
从不增加,而是在 40 秒内保持为零count
既没有通过激活start
设置为 0,也没有通过显示的停用设置(即state
从C
到A
).
你知道为什么吗?
P.S。我知道我绝对不是 运行 合适的测试平台。所以即使我应该,也请不要提醒我,除非你知道这是我问题答案的一部分。
强制更新信号值不会生成事件。
参见 IEEE Std 1076-2008 14.7.3.4 信号更新,第 3 段
... If updating a signal causes the current value of that signal to change, then an event is said to have occurred on the signal, unless the update occurs by application of the
vhpi_put_value
function with an update mode ofvhpiDeposit
orvhpiForce
to an object that represents the signal. ...
可能与 Modelsim 的力或 FLI 使用的机制相同。
有测试台:
library ieee;
use ieee.std_logic_1164.all;
entity slm_tb is
end entity;
architecture foo of slm_tb is
-- Input ports
signal clk: std_logic := '1';
signal message: std_logic := '0';
signal display: std_logic := '0';
signal start: std_logic := '1';
-- Output ports
signal seg14: std_logic_vector (13 downto 0);
signal lengthLED: std_logic;
begin
DUT:
entity work.sauvezlesmorses
port map (
clk => clk,
message => message,
display => display,
start => start,
seg14 => seg14,
lengthLED => lengthLED
);
-- force -freeze sim:/sauvezlesmorses/clk 1 0, 0 {25000000000 ps} -r {50 ms}
-- force -freeze sim:/sauvezlesmorses/display 0 0, 1 {9000000000000 ps} -r {18 sec}
-- force -freeze sim:/sauvezlesmorses/message 0 0, 1 {3200000000000 ps} -r {6.4 sec}
-- force -freeze sim:/sauvezlesmorses/start 1 0 -cancel {0.5 sec}
-- run 40 sec
-- stimulus generators:
CLOCK:
process
begin
wait for 25 ms;
clk <= not clk;
if now > 40 sec then
wait;
end if;
end process;
DISP:
process
begin
wait for 9 sec;
display <= not display;
if now > 35 sec then -- stop simulation at 40 sec
wait;
end if;
end process;
MSG:
process
begin
wait for 3.2 sec;
message <= not message;
if now > 35 sec then
wait;
end if;
end process;
ST:
process
begin
wait for 0.5 sec;
start <= 'U';
wait;
end process;
end architecture;
你确实得到了事件: