ฉันจะระบุสัญญาณ“ ไม่สนใจ” ใน VHDL ได้อย่างไร?


11

ในหลักสูตรการออกแบบลอจิกที่เราทุกคนได้เรียนรู้ว่ามันเป็นไปได้ที่จะลดการทำงานตรรกะเช่นโดยการใช้แผนที่ Karnaugh หรืออัลกอริทึมควิน-คสัส นอกจากนี้เรายังได้เรียนรู้ว่าค่า"ไม่สนใจ"เพิ่มโอกาสในการลดขนาด

ตัวอย่างเช่นใช้ไฟล์ลงทะเบียน write_addressและwrite_dataสัญญาณไม่ได้เรื่องจริงๆเมื่อสัญญาณwrite_enable '0'ดังนั้นพวกเขาควรจะกำหนดค่า "ไม่สนใจ" เพื่อให้การเพิ่มประสิทธิภาพมากขึ้นในตรรกะที่ขับสัญญาณเหล่านี้ (เช่นไม่ได้อยู่ในไฟล์ลงทะเบียนตัวเอง)

วิธีที่ถูกต้องในการระบุค่า "Don't Care" ใน VHDL คือเพื่อให้เครื่องมือการสังเคราะห์มีพื้นที่มากขึ้นสำหรับการเพิ่มประสิทธิภาพที่เป็นไปได้?


จนถึงตอนนี้ฉันได้พบสิ่งต่อไปนี้ซึ่งอาจเหมาะสม แต่ฉันไม่แน่ใจจริงๆว่าข้อดีข้อเสียของแต่ละวิธีคืออะไร:

  • เพียงไม่กำหนดสัญญาณ ดูเหมือนว่ามันจะทำงานได้ อย่างไรก็ตามฉันพบว่ามันไม่ทำงานเมื่อคุณต้องการกำหนด "ไม่ทำอะไรคงที่" บางrecordประเภทเนื่องจากค่าคงที่บันทึกต้องได้รับการระบุอย่างสมบูรณ์ (อย่างน้อย Modelsim บอกฉันอย่างนั้น)
  • std_logic_1164แพคเกจที่กำหนดค่าสำหรับ'-' -- Don't care std_ulogicดูเหมือนว่านี่เป็นตัวเลือกที่ถูกต้องสำหรับความหมายที่ชัดเจนว่า "ไม่สนใจ" แต่ฉันไม่เคยเห็นมันมาใช้เลย (ยกเว้นในโครงสร้าง VHDL-2008 ที่ไม่เกี่ยวข้องcase?)
  • Modelsim ใช้ค่า'X'เพื่อแสดงสัญญาณที่ไม่ได้กำหนด อย่างไรก็ตามฉันไม่แน่ใจว่าเครื่องมือการสังเคราะห์เข้าใจการ'X'มอบหมาย - อย่างชัดเจนว่า "ไม่สนใจ"

ต่อไปนี้เป็นตัวอย่างโค้ดขนาดใหญ่เกินไปสำหรับการชี้แจงซึ่งฉันได้เตรียมข้อมูล'-'เบื้องต้นเกี่ยวกับการไม่สนใจสัญญาณด้วย

ที่คุณสามารถดูสัญญาณcontrol.reg_write_addressสามารถมีค่าที่แตกต่างกัน 3: "----", และinstruction(11 downto 8); instruction(3 downto 0);ตอนนี้ฉันคาดว่าสิ่งนี้จะถูกสังเคราะห์เป็นมัลติเพล็กเซอร์ 2 อินพุทถ้า'-'ตีความว่า "ไม่สนใจ" หากฉันเริ่มต้นสัญญาณด้วย(others => '0')แทน'-'เครื่องมือจะต้องสร้างมัลติเพล็กเซอร์ 3 อินพุทแทน

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และwrite_data? การเพิ่มประสิทธิภาพแบบใดที่คุณคาดว่าจะเกิดขึ้น
fru1tbat

ฉันหวังว่าตัวอย่างจะทำให้ชัดเจนยิ่งขึ้นในสิ่งที่ฉันต้องการบรรลุ
ฟริตซ์

คำตอบ:


9

ฉันจะปล่อยให้ผู้เชี่ยวชาญ LRM ให้คำตอบโดยละเอียด แต่ในระยะสั้นแนวทางของคุณควรถูกต้อง - ฉันทำการทดสอบอย่างรวดเร็วด้วย Quartus รุ่นล่าสุดและจัดการ'-'เหมือนที่ควร - ตรรกะที่สร้างขึ้นลดลง ตามที่คาดไว้เมื่อเอาท์พุทเป็นค่าเริ่มต้นเป็น'-'( 'X'ทำงานด้วยวิธี) เพิ่มเติมเกี่ยวกับวิธีการที่คุณระบุไว้:

  • การไม่กำหนดสัญญาณไม่ใช่ตัวเลือกสำหรับตัวอย่างแน่นอนถ้าคุณไม่ต้องการสลัก หากเป็นกระบวนการที่มีการโอเวอร์คล็อกคุณจะดีขึ้นเล็กน้อย แต่คุณจะยังคงได้รับสิ่งที่คุณไม่ต้องการ บางทีฉันอาจขาดความตั้งใจของคุณที่นี่

  • '-'ตามที่ระบุไว้ก่อนหน้านี้อาจเป็นตัวเลือกที่ดีที่สุดด้วยเหตุผลทางความหมายและการปฏิบัติ

  • ขึ้นอยู่กับสิ่งที่คุณหมายถึงโดย "ไม่ได้กำหนด" 'X'เป็นเทคนิค "ไม่ทราบ" 'U'ใช้สำหรับสัญญาณที่ไม่กำหนดค่าเริ่มต้นซึ่ง ModelSim แสดง"X"สำหรับการแทนค่าฐานสิบหก 'X'ดูเหมือนว่าจะใช้งานได้ตามที่ฉันได้กล่าวไว้ข้างต้น

อีกทางเลือกหนึ่งคือการเพิ่มประสิทธิภาพด้วยตนเองและลบกรณีหนึ่งออกจากการทดสอบอย่างชัดเจน:

if instruction(15 downto 8) = "11111001" then
  write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 4)), 16));
else
  write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 0)), 16));
end if;

สิ่งนี้มีข้อเสียที่สำคัญ (ส่วนใหญ่เกี่ยวข้องกับความชัดเจนของโค้ด) และฉันอาจเลือกใช้วิธีแก้ปัญหาที่เหมาะสมกว่า

อนึ่ง'-'ก็มักจะใช้กับstd_match()ซึ่งฉันจะพิจารณาใช้สำหรับการถอดรหัสของคุณเช่น:

if std_match(instruction(15 downto 8), "1100----") then

case?แม้ว่าที่จุดที่คุณอาจจะดีกว่าเพียงแค่ใช้


6

กล่าวโดยย่อ: เป็น VHDL ที่ถูกกฎหมายและโดยทั่วไปจะรองรับโดยเครื่องมือการสังเคราะห์

อย่างไรก็ตามมันค่อนข้างแปลกที่จะเห็นมันใช้ ฉันไม่รู้จริงๆว่าทำไม รหัสของคุณดูเหมือนว่าฉันจะเป็นตัวอย่างที่ดีเมื่อมันจะมีความหมายที่จะใช้มัน

อย่างไรก็ตามมีข้อเสียเปรียบอย่างหนึ่งที่ควรทราบ: ในการสังเคราะห์ฟังก์ชั่นการขับเคลื่อนผลลัพธ์ที่ไม่เกี่ยวข้องนั้นอาจแตกต่างกันระหว่างการสังเคราะห์ สิ่งนี้ทำให้การสังเคราะห์น้อยลง หากมีการใช้เอาต์พุตที่กำหนดว่าไม่สนใจ (โดยไม่ได้ตั้งใจ) สิ่งนี้จะทำให้เกิดข้อผิดพลาดในการค้นหาได้ยากขึ้น

การสนับสนุนเครื่องมือ

อย่างน้อยเครื่องมือต่อไปนี้จะยอมรับว่าไม่ใส่ใจและใช้ประโยชน์จากความเป็นไปได้ในการเพิ่มประสิทธิภาพ:

  • Xilinx (อ้างอิง: "คู่มือผู้ใช้ XST")
  • Altera (อ้างอิง: "รูปแบบการเข้ารหัส HDL ที่แนะนำ")
  • ขยาย (อ้างอิง: "คู่มืออ้างอิงการเชื่อมโยง")

Xilinx และ Altera จะปฏิบัติ'-'และ'X'เป็นไม่สนใจ synplify จะปฏิบัติเหล่านั้นและนอกจากนี้'U'และ'W'(อ่อน) เป็นไม่สนใจ


1
ฉันมีแอปพลิเคชั่นข้อเสียอื่นอีก รหัสทำงานในการจำลอง แต่ไม่ได้อยู่ใน FPGA if signal = '1' then a; else b; end if;เพราะรหัสของฉันดูเหมือน: แต่น่าเสียดายsignalไม่ได้1หรือแต่0 -ดังนั้นในการจำลองelseสาขาถูกประหารชีวิต แต่ในฮาร์ดแวร์-กลายเป็น a 1ดังนั้นสาขาที่แท้จริงจึงถูกประหาร ...
Fritz

ใช่ฉันเคยมีข้อบกพร่องที่คล้ายกันผ่านการจำลอง แต่ส่วนใหญ่ในกรณีของฉันมี'U's, ที่พบบ่อยในการเริ่มต้นของการจำลองที่มีการใช้ที่นำไปสู่การelseบล็อกรหัสที่ถูกประหารชีวิต มันจะวิเศษถ้าเงื่อนไขใด ๆ สามารถทำเพื่อเผยแพร่'U's, คล้ายกับพฤติกรรมของการแสดงออกบูลีนพร้อมกัน
Carl

หลังจากฉันพบข้อผิดพลาดนั้นฉันแน่ใจว่าจะเขียนสิ่งที่ชอบif signal = '1' then output <= '1'; elsif signal='0' then output <= '0'; else output <= '-'; end if;เสมอ และผมเพิ่มความต่อไปนี้เพื่อลงทะเบียนและความทรงจำทั้งหมด: และassert not is_X(write_enable) report "we=" & str(A_write_enable) severity ERROR; พลัสเหมือนกันสำหรับif write_enable = '1' then assert not is_X(write_addr) report "write_addr=str(write_addr) severity ERROR; end if; write_dataร่วมกันที่ควรจับข้อผิดพลาดเหล่านี้เกือบทั้งหมด
Fritz

นั่นเป็นวิธีการ แต่ก็เป็นวิธีที่ verbose สำหรับฉันเกินไป ฉันต้องการความเป็นไปได้นี้ภายในภาษา VHDL
Carl

1
ใช่แล้ว VHDL ค่อนข้างละเอียด แต่นั่นเป็นเพียงวิธี VHDL : D ในทางกลับกันมันชัดเจนมากและไม่ได้ทำ "มนต์ดำ" ที่ด้านหลังของฉันซึ่งฉันพบว่าค่อนข้างดี (เปรียบเทียบ The Zen of Python "Explicit is better than implicit")
ฟริตซ์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.