ตรรกะหรือรีเซ็ตและล้าง?
ฉันกำลังพยายามหาแนวทางปฏิบัติที่ดีที่สุดในการใช้การรีเซ็ต (ใช้ async, ซิงค์ล้าง) และอินพุตที่ชัดเจน ฉันมีกระบวนการที่ต้องรันนาฬิกาที่ได้รับตรรกะ (NCO) ที่เรียกว่า code_clk ช้ากว่า แต่ซิงโครนัสกับ clk จริง กระบวนการนี้เกี่ยวข้องกับการลงทะเบียน Linear Feedback Shift ที่ต้องรีเซ็ตเป็น 1 ทั้งหมดเพื่อเริ่มลำดับการสร้างรหัสหลังจากที่การรีเซ็ตถูกยกขึ้น อย่างไรก็ตามตลอดการดำเนินการกระบวนการควรรีเซ็ตเป็น 1 ทั้งหมดเมื่อมีการเลือกชุดก๊อกใหม่ (T1 และ T2) สำหรับเอาต์พุตแน่นอนเพื่อรีเซ็ตลำดับการสร้างรหัสและตรวจสอบให้แน่ใจว่ารหัสใหม่ถูกต้องกับใหม่ ก๊อก สิ่งนี้ทำได้ด้วยอินพุต clr แบบซิงโครนัสแยกต่างหากซึ่งจะค้างไว้สูงสำหรับรอบนาฬิการะบบเดียวในขณะที่เลื่อนก๊อกไปรอบ ๆ
นี่คือรหัสของฉัน:
process(code_clk, reset, clr)
begin
if(reset='0' or clr='1') then
-- EARLY LFSR
EG1(1 to 10) <= (others => '1');
EG2(1 to 10) <= (others => '1');
early_code <= '0';
delay_os <= '0';
elsif(falling_edge(code_clk)) then
if(delay_os='0') then
-- LFSR feedbacks for early code
EG1(2 to 10) <= EG1(1 to 9);
EG2(2 to 10) <= EG2(1 to 9);
EG1(1) <= EG1(3) xor EG1(10);
EG2(1) <= EG2(2) xor EG2(3) xor EG2(6) xor EG2(8) xor EG2(9) xor EG2(10);
early_code <= EG1(10) xor EG2(T1) xor EG2(T2); -- C/A output of early LFSR
else
-- delay of code chips commanded - do not shift this time
delay_os <= '0';
end if;
late_code <= early_code; -- one half chip delay from prompt code
elsif(rising_edge(code_clk)) then
prompt_code <= early code; -- one half chip delay from early code
end if;
end process;
เงื่อนไข if (reset = '0' หรือ clr = '1') จะกระโดดใส่ฉันว่าเป็นสไตล์ที่ไม่ดี ดูเหมือนว่าสถานการณ์หนึ่งที่การสังเคราะห์จะสร้างตรรกะที่ไม่จำเป็นหรือการหน่วงเวลาเนื่องจากเส้นทางการรีเซ็ตไม่ตรงไปตรงมา ฉันสามารถทำได้หรือควรลองอย่างอื่น ความชัดเจนจะต้องเกิดขึ้นทันทีดังนั้นฉันต้องทำให้กระบวนการหมดไปจากนาฬิการะบบหรืออย่างอื่น นี่ถือเป็นการปฏิบัติที่ดีหรือไม่?
คำตอบ
สัญชาตญาณของคุณสำหรับเงื่อนไขถ้าถูกต้อง เครื่องมือสังเคราะห์บางอย่างอาจเข้าใจในสิ่งที่คุณกำลังพยายามทำ แต่หลายคนไม่เข้าใจเนื่องจากสิ่งที่คุณเขียนไม่ใช่รูปแบบที่กำหนดไว้ดังนั้นเครื่องมืออาจไม่อนุมานสิ่งที่คุณต้องการในแบบที่คุณต้องการ มาตรฐาน (หากมีสิ่งนั้น) / วิธีที่ได้รับการยอมรับในการเขียนสิ่งที่คุณพยายามจะบรรลุมีดังนี้:
process(clk, reset)
begin
if reset = '1' then -- async reset
-- your code here
elsif Rising_edge(clk) then
if sync_clr = '1' then -- sync clear
-- your code here
end if;
end if;
end process;
ฉันทราบว่าการรีเซ็ตของคุณทำงานอยู่ในระดับต่ำซึ่งมีแนวโน้มที่จะขมวดคิ้วภายใน FPGA (เกี่ยวข้องกับการอ่านโค้ดมากกว่าปัญหาทางสถาปัตยกรรมจริง)
แต่เดี๋ยวก่อน! ทำไมเรื่องนี้ถึงมีความสำคัญ?
ซึ่งรวมถึงสถาปัตยกรรมส่วนบุคคลของ FPGA ที่คุณใช้อยู่ ด้านล่างนี้คือส่วนย่อยของแผนภาพบล็อกสำหรับ Cyclone V Adaptive Logic Module
เมื่อดูที่รีจิสเตอร์คุณจะเห็นว่ามีเพียงตัวควบคุมเดียว - CLR ที่ด้านบนของแผนภาพคุณจะเห็นสัญญาณaclr [1: 0]เข้ามาใน ALM เมื่อคุณสรุปการรีเซ็ตแบบ async นี่คือสิ่งที่ตั้งค่าไว้ โปรดทราบว่า ALM นี้มีการลงทะเบียน 4 รายการ แต่มีสัญญาณรีเซ็ตเพียง 2 รายการเท่านั้นที่ใช้ร่วมกันโดยคู่ สิ่งนี้มีความหมายสำหรับจำนวน ALM ที่ใช้
คุณยังสามารถเห็นสัญญาณซิงโครนัสที่ชัดเจน ( sclr ) และสัญญาณโหลดซิงโครนัส ( syncload ) ที่เข้ามาใน ALM สิ่งเหล่านี้แชร์โดยทั้ง 4 รีจิสเตอร์ จะใช้วงจรเหล่านี้หากอนุมานในรหัส แผนภาพมีรายละเอียดเพียงพอที่จะเข้าใจวิธีการทำงานของสัญญาณ
sclrตั้งใจให้แอคทีฟสูง มีการกลับด้านและ AND ด้วยข้อมูลที่ฟีดอินพุต D ของรีจิสเตอร์ นั่นหมายความว่าเมื่อสูง 0 จะถูกป้อนไปยังอินพุต D และ Q จะอัปเดตเป็น 0 ในรอบนาฬิกาถัดไป
syncloadไดรฟ์มัลติเพล็กเซอร์ซึ่งเลือกเอาต์พุตจาก LUTs หรือ datae0 ซึ่งมาจากภายนอก ALM
สังเกตว่าไม่มีชุดอะซิงโครนัส หากคุณเขียนสิ่งนี้เครื่องมือจะไม่สามารถจับคู่สิ่งนี้กับสถาปัตยกรรมของอุปกรณ์และใช้งานโดยใช้ LUT แทน สิ่งนี้เหมือนกันสำหรับทุกการควบคุมที่ไม่ได้เป็นส่วนหนึ่งของสถาปัตยกรรมอุปกรณ์
Xilinx มีเอกสารไวท์เปเปอร์ที่อธิบายรายละเอียดเพิ่มเติม: https://www.xilinx.com/support/documentation/white_papers/wp275.pdf