Trong các khóa học Thiết kế Logic, tất cả chúng ta đều học được rằng có thể giảm thiểu chức năng logic, ví dụ bằng cách sử dụng bản đồ Karnaugh hoặc thuật toán Quine siêu McCluskey . Chúng tôi cũng học được rằng các giá trị "Không quan tâm" làm tăng tiềm năng giảm thiểu.
Ví dụ lấy một tập tin đăng ký. Các tín hiệu write_address
và write_data
không thực sự quan trọng khi write_enable
tín hiệu là '0'
. Vì vậy, chúng nên được gán một giá trị "Không quan tâm" để cho phép tối ưu hóa nhiều hơn trong logic đang điều khiển các tín hiệu này (tức là không phải trong chính tệp đăng ký).
Cách chính xác để xác định các giá trị "Không quan tâm" như vậy trong VHDL là gì để cho phép công cụ tổng hợp có nhiều chỗ hơn cho các tối ưu hóa có thể?
Cho đến nay tôi đã tìm thấy những điều sau đây có thể phù hợp. Nhưng tôi không thực sự chắc chắn những ưu và nhược điểm của mỗi phương pháp là gì:
- Đơn giản là không gán tín hiệu. Điều này có vẻ như nó có thể làm việc. Tuy nhiên tôi thấy rằng nó không hoạt động khi bạn muốn xác định một loại "không làm gì liên tục" của một số
record
loại, vì các hằng số bản ghi cần phải được chỉ định đầy đủ (ít nhất là Modelim nói với tôi như vậy). - Các
std_logic_1164
gói xác định giá trị'-' -- Don't care
chostd_ulogic
. Có vẻ như đây là lựa chọn chính xác về mặt ngữ nghĩa cho một "không quan tâm" rõ ràng, nhưng tôi chưa bao giờ thấy nó được sử dụng ở bất cứ đâu (ngoại trừ trong cáccase?
cấu trúc VHDL-2008 không liên quan ). - Modelim sử dụng giá trị
'X'
để hiển thị các tín hiệu không xác định. Tuy nhiên tôi không chắc các công cụ tổng hợp có hiểu một sự phân bổ rõ ràng'X'
là "không quan tâm" hay không.
Đây là một đoạn mã đơn giản hóa để làm rõ, nơi tôi đã khởi tạo các tín hiệu không quan tâm '-'
.
Như bạn có thể thấy, tín hiệu control.reg_write_address
có thể có 3 giá trị khác nhau: "----"
, instruction(11 downto 8);
và instruction(3 downto 0);
. Bây giờ tôi hy vọng điều này sẽ được tổng hợp thành một bộ ghép kênh 2 đầu vào nếu '-'
được hiểu là "không quan tâm". Nếu tôi đã khởi tạo tín hiệu (others => '0')
thay vì '-'
, công cụ sẽ phải tạo bộ ghép kênh 3 đầu vào thay thế.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package mytypes is
type control_signals_t is record
write_enable : std_logic;
write_address : std_ulogic_vector(3 downto 0);
read_address : std_ulogic_vector(3 downto 0);
end record;
-- All members of this constant must be fully specified.
-- So it's not possible to simply not assign a value.
constant CONTROL_NOP : control_signals_t := (
write_enable => '0',
write_address => (others => '-'),
read_address => (others => '-')
);
end package;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library cfx;
use cfx.mytypes.all;
entity control_unit is
port(
instruction : in std_ulogic_vector(15 downto 0);
write_data : out std_ulogic_vector(15 downto 0);
ctrl : out control_signals_t
);
end entity;
architecture rtl of control_unit is
begin
decode_instruction : process(instruction) is
begin
-- Set sensible default values that do nothing.
-- Especially all "write_enable" signals should be '0'.
-- Everything else is mostly irrelevant (don't care).
ctrl <= CONTROL_NOP;
write_data <= (others => '-');
if instruction(15 downto 12) = "1100" then
-- Load 8 bit of data into the register file
ctrl.write_enable <= '1';
write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 0)), 16));
ctrl.write_address <= instruction(11 downto 8);
elsif instruction(15 downto 8) = "11111001" then
-- Load 4 bit of data into the register file
write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 4)), 16));
ctrl.write_address <= instruction(3 downto 0);
elsif instruction(15 downto 8) = "10110101" then
-- Read from the register file. Don't use the write signals at all.
ctrl.read_address <= instruction(3 downto 0);
end if;
end process;
end architecture;
write_address
vàwrite_data
không? Tối ưu hóa nào bạn mong đợi sẽ diễn ra?