Thoạt nhìn, bạn sẽ mong đợi mã nguồn VHDL bên dưới hoạt động như một thanh ghi thay đổi. Trong đó q, theo thời gian sẽ là
"UUUU0", "UUU00", "UU000", "U0000", "00000", ....
nhưng thay vào đó, nó luôn luôn U
sau năm (hoặc nhiều hơn) chu kỳ đồng hồ liên tiếp.
Tại sao lại thế này?
Mã này thực sự là một phiên bản đơn giản hơn nhiều của một mô phỏng phức tạp hơn nhiều. Nhưng nó cho thấy các triệu chứng mà tôi thấy.
Nó thể hiện kết quả thú vị và bất ngờ này trong quá trình mô phỏng theo cả ModelSim và ActiveHDL, tôi đã không thử các trình giả lập khác và (thứ hai là giải thích nguyên nhân) muốn biết liệu những người khác có hành động tương tự không.
Để trả lời đúng câu hỏi này, bạn phải hiểu rằng:
- Tôi biết đây không phải là cách tốt nhất để thực hiện đăng ký thay đổi
- Tôi biết để tổng hợp RTL nên có một thiết lập lại.
- Tôi biết một mảng của std_logic là một std_logic_vector.
- Tôi biết các toán tử tổng hợp
&
,.
Những gì tôi cũng đã tìm thấy:
- Nếu sự phân công
temp(0)<='0';
được di chuyển bên trong quá trình, nó hoạt động. - Nếu vòng lặp được mở ra (xem mã nhận xét), nó hoạt động.
Tôi sẽ nhắc lại rằng đây là phiên bản rất đơn giản với thiết kế phức tạp hơn nhiều (đối với CPU có đường ống), được cấu hình để hiển thị hoàn toàn các kết quả mô phỏng bất ngờ. Các loại tín hiệu thực tế chỉ là một sự đơn giản hóa. Vì lý do này, bạn phải xem xét câu trả lời của mình với mã theo mẫu.
Tôi đoán là trình tối ưu hóa của công cụ mô phỏng VHDL bị nhầm lẫn (hoặc có thể theo thông số kỹ thuật) không bận tâm để chạy các biểu thức bên trong vòng lặp vì không có tín hiệu bên ngoài thay đổi, mặc dù tôi có thể từ chối điều này bằng cách đặt vòng lặp không được bao bọc trong một vòng lặp.
Vì vậy, tôi hy vọng rằng câu trả lời cho câu hỏi này liên quan nhiều hơn đến các tiêu chuẩn cho mô phỏng VHDL của cú pháp VHDL không rõ ràng và cách các công cụ mô phỏng VHDL thực hiện tối ưu hóa của chúng, thay vì ví dụ mã được đưa ra có phải là cách tốt nhất để làm gì đó hay không.
Và bây giờ với mã tôi đang mô phỏng:
library ieee;
use ieee.std_logic_1164.all;
entity test_simple is
port (
clk : in std_logic;
q : out std_logic
);
end entity;
architecture example of test_simple is
type t_temp is array(4 downto 0) of std_logic;
signal temp : t_temp;
begin
temp(0) <= '0';
p : process (clk)
begin
if rising_edge(clk) then
for i in 1 to 4 loop
temp(i) <= temp(i - 1);
end loop;
--temp(1) <= temp(0);
--temp(2) <= temp(1);
--temp(3) <= temp(2);
--temp(4) <= temp(3);
end if;
end process p;
q <= temp(4);
end architecture;
Và băng ghế thử nghiệm:
library ieee;
use ieee.std_logic_1164.all;
entity Bench is
end entity;
architecture tb of bench is
component test_simple is
port (
clk : in std_logic;
q : out std_logic
);
end component;
signal clk:std_logic:='0';
signal q:std_logic;
signal rst:std_logic;
constant freq:real:=100.0e3;
begin
clk<=not clk after 0.5 sec / freq;
TB:process
begin
rst<='1';
wait for 10 us;
rst<='0';
wait for 100 us;
wait;
end process;
--Note: rst is not connected
UUT:test_simple port map (clk=>clk,q=>q) ;
end architecture;
temp(0)
vì không có "sự kiện" nào liên quan đến hằng số theo nghĩa đen. Đặt nhiệm vụ bên trong process
tạo ra một liên kết với các sự kiện đồng hồ làm cho nó hoạt động. Tôi tự hỏi nếu thêm một after
mệnh đề vào bài tập sẽ là một cách giải quyết tiềm năng.