คำถามสัมภาษณ์ VHDL - ตรวจสอบว่าตัวเลขสามารถหารด้วย 5 ได้โดยไม่เหลือ


24

ฉันเห็นคำถามสัมภาษณ์ที่ดีสำหรับ VHDL - สร้างระบบที่ได้รับตัวเลขและตรวจพบว่าสามารถหารด้วย 5 ได้โดยไม่เหลือ ฉันพยายามที่จะแก้ปัญหาด้วยเครื่องสถานะ (ฉันคิดว่าพวกเขาไม่ต้องการให้คุณใช้modหรือrem ) และในขณะที่ฉันประสบความสำเร็จครั้งแรก (ตัวเลขเช่น 5, 10, 15, และตัวเลขเช่น 20, 40, 80 ใช้ได้ ) ตัวเลขอื่น ๆ เช่น 130, 75 และอื่น ๆ ล้มเหลวสำหรับฉัน

ฉันจะแสดงเครื่องสถานะของฉัน แต่มันเป็นระเบียบสมบูรณ์ (ไม่ใช่รหัสมันเป็นรูปวาด) และเหมือนที่ฉันพูดไม่ทำงาน

โดยพื้นฐานแล้วสิ่งที่ฉันพยายามจะทำคือเขียนเลขฐานสองที่หารด้วย 5 ได้และสร้างเครื่องสถานะที่เหมาะกับพวกเขา

ฉันจะดีใจถ้าคุณสามารถแสดงให้ฉันเห็นวิธีการแก้ปัญหานี้และวิธีคิดเมื่อเผชิญหน้ากับสิ่งนี้

ขอขอบคุณ!


คุณหมายถึงการใช้งานฮาร์ดแวร์ (สังเคราะห์ได้) ไม่ใช่แค่รหัสเพื่อทดสอบว่าตัวอักษรจำนวนเต็มหารด้วย 5 ได้ (เช่นสำหรับ testbench)
smci

@smci ที่จริงฉันขอแผนผัง / ภาพวาดของเครื่องรัฐ แต่รหัสของเครื่องรัฐนั้นจะไม่เจ็บ Dave Tweed ตอบคำถามอย่างสมบูรณ์แบบ
Eran

แล้วผมก็ retitle * "คำถามสัมภาษณ์ VHDL - CCT การตรวจสอบถ้า ..."
smci

ตอบที่นี่โดย egreg math.stackexchange.com/a/2569882/213607อาจให้แรงบันดาลใจสำหรับวิธีการที่คล้ายคลึงกันมากขึ้น
คณิตศาสตร์ที่

คำตอบ:


37

การดำเนินการที่เหลือในแบบอนุกรมนั้นเป็นเรื่องง่ายมาก ข้อสันนิษฐานที่สำคัญคือข้อมูลมาใน MSB ก่อนถ้ามันเป็นอนุกรม คุณต้องการเพียง N States ในการคำนวณโมดูโลที่เหลือเริ่มต้นในสถานะ "0" และถ้าคุณลงเอยในสถานะ "0" หลังจากบิตสุดท้าย (มันไม่สำคัญว่ามีกี่บิต) ส่วนที่เหลือคือ ศูนย์.

แผนผัง

จำลองวงจรนี้ - แผนผังที่สร้างโดยใช้CircuitLab

ลองคิดดูว่าคุณจะแบ่งเวลานานแค่ไหนหากสิ่งเดียวที่คุณต้องการติดตามคือส่วนที่เหลือ:

process (clk)
begin
  if rising_edge(clk) then
    if reset = 1 then
      state <= 0;
    else
      if (state & din) >= N then
        state <= (state & din) - N;
      else
        state <= state & din;
      end if;
    end if;
  end if;
end process;

6
ว้าวฉันเห็นว่ามันใช้งานได้ แต่คุณสามารถอธิบายได้ว่าคุณคิดอย่างไรกับกลไกรัฐ? จุดเริ่มต้นคืออะไร ฉันไม่เคยเห็นสิ่งนี้ทำมาก่อนฉันแค่อยากรู้ว่าตรรกะอยู่ที่ว่าจะทำอย่างไรกับมัน?
zoder

7
แผนภาพสถานะเป็นเพียงสิ่งที่คุณได้รับจากรหัส VHDL สำหรับกรณีเฉพาะของ N = 5 กล่าวอีกนัยหนึ่งถ้ารัฐแทนส่วนที่เหลือในปัจจุบันสถานะถัดไปคือสิ่งที่คุณได้รับเมื่อคุณเลื่อนสถานะซ้ายหนึ่งบิตเพิ่มบิตอินพุตให้กับมันแล้วลบ 5 หากจำเป็น
Dave Tweed

3
นี่ถ้าสวยงามฉันจะต้องประทับใจอย่างแท้จริงถ้ามีคนมาด้วยตนเองในการสัมภาษณ์ และจากนั้นฉันก็ขอให้พวกเขาแสดงความคิดเห็นว่าผลลัพธ์การสังเคราะห์จะแตกต่างไปอย่างไรเมื่อเทียบกับการใช้ตัวดำเนินการ rem เพื่อประมวลผลเวกเตอร์แบบเต็มทุกรอบนาฬิกา
Casperrw

8
@zoder รัฐเป็นสารตกค้าง mod 5; 0 ลูกศรชี้ไปที่2n mod 5และลูกศรชี้ไปที่(2n + 1) mod 51
ฮอบส์

2
คุณสามารถเพิ่มการประกาศของstate, dinและNรหัสของคุณหรือไม่
mkrieger1

15

คุณยังสามารถออกแบบเครื่องสถานะได้หากข้อมูลมาถึง LSB ก่อน:

การแสดงกราฟิกของ DFA ดังที่อธิบายไว้ท้ายคำตอบนี้ในภาคผนวก

การดำรงอยู่ของออโตเมติก จำกัด (DFA) ที่กำหนดขึ้นได้ดังต่อไปนี้โดยตรงจากคำตอบอื่นซึ่งอธิบาย DFA สำหรับ MSB-first เนื่องจากภาษาที่ยอมรับโดย DFAs เป็นภาษาปกติและเป็นที่ทราบกันว่าปิดภายใต้การกลับรายการ (เช่นดูที่นี่ ) จึงต้องมี DFA ซึ่งยอมรับภาษาต่อไปนี้:

}L={W{0,1}* * * *| ถอยหลัง(W)10 หารด้วย 5}

การก่อสร้าง

  1. คัดลอก MSB แรก DFA จากคำตอบของเดฟทวีด ฉันใช้เครื่องมือออโตเมติก JFLAPสำหรับสิ่งนั้น

  2. ใช้ขั้นตอนวิธีการเปลี่ยนแปลงที่ชัดเจนสำหรับการพลิกผัน DFA เช่นตามที่อธิบายไว้ใน CS.SE: ออกแบบ DFA และย้อนกลับของมัน
    คุณสามารถเห็นผลลัพธ์ (ไม่ จำกัด ขนาด) ของขั้นตอนนี้ในการแก้ไขคำตอบเก่านี้




  3. Q0Q1

อันที่จริงหุ่นยนต์ที่เกิดขึ้นจะให้คำตอบที่ถูก

ตารางที่มีสองคอลัมน์ "อินพุต" และ "ผลลัพธ์" แสดงรายการว่าผลลัพธ์จำนวนต่างๆใน "ยอมรับ" หรือ "ปฏิเสธ"


ARอีโวลต์5=(Q,Σ,δ,Q0,F)Q={Q0,Q1,Q2,Q3,Q4}Σ={0,1}F={Q0}δ

δ(Q0,0)=Q0,δ(Q0,1)=Q1δ(Q1,0)=Q4,δ(Q1,1)=Q3δ(Q2,0)=Q1,δ(Q2,1)=Q2δ(Q3,0)=Q2,δ(Q3,1)=Q4δ(Q4,0)=Q3,δ(Q4,1)=Q0


หากคุณมีปัญหาในการย้อนกลับของ DFA คุณสามารถย้อนกลับสมการได้แทน: new_state = state * 2 + อินพุตคุณสามารถใช้ (new_state - input) / 2 = state จากนั้นสลับสถานะและ new_state DFA สำหรับสมการใหม่ควรแก้ปัญหาแรกของ LSB
Eyal

ทำไม q3 & q4 จึงติดป้ายกำกับว่า & ไม่ตรงกันข้าม สลับเลเบล q3 & q4 และเครื่องใช้อัลโก "ครึ่งหนึ่ง (mod 5) & เพิ่มบิตอินพุต"
Rosie F

2
@RosieF: วลี "halve (mod 5)" อาจใช้คำอธิบายเพิ่มเติมสำหรับผู้ที่ไม่คุ้นเคยกับคณิตศาสตร์ไม่ต่อเนื่อง การหารในบริบทนี้เป็นการเพิ่มจำนวนฐานใด ๆ ที่จำเป็นเพื่อให้จำนวนหารเท่ากันดังนั้น 3/2 (mod 5) จะเป็น (3 + 5) / 2 เช่น 4
supercat

7

วิธีหนึ่งที่จะเกิดขึ้นกับเครื่องสถานะ (MSB แรก) มีดังนี้:

  1. Nจำนวนที่ได้รับเพื่อให้ห่างไกล M = N mod 5สมมติว่าคุณรู้ว่าส่วนที่เหลือ

  2. N' = N*2 + bมีบิตใหม่ที่เข้ามาในและค่าใหม่อยู่ในขณะนี้

  3. M' = (N*2 + b) mod 5 = (M*2 + b) mod 5ที่เหลือใหม่แล้ว

นี่ง่ายพอที่จะจัดระเบียบด้วยมือ:

    M b | M'
------------------
    0 0 | 0
    1 0 | 2
    2 0 | 4
    3 0 | 1
    4 0 | 3
    0 1 | 1
    1 1 | 3
    2 1 | 0
    3 1 | 2
    4 1 | 4

ซึ่งตรงกับกลไกของรัฐในคำตอบของ Dave Tweed


5

เราหวังว่าคำถามสัมภาษณ์คือคุณจะแก้ปัญหาอย่างไรแทนที่จะใช้ VHDL หรือ Verilog รายละเอียดภาษาตรงไปตรงมาเมื่อคุณมีอัลกอริทึม

S=0S(2S+d) พอควร 5 SS,dS=0,,4

S=0,k=0S(S+2kd) พอควร 5,kk+1k24=1 พอควร 5S(S+2kd) พอควร 5,k(k+1) พอควร 4S,k,d(S,k)S=0,,4k=0,,3


3

ขึ้นอยู่กับสิ่งที่ VHDL กำลังเขียนอยู่คุณอาจต้องการใช้แนวทางที่อธิบายว่าเป็นการคำนวณโดยตรงและการผสม การรับหมายเลขอาจหมายถึงว่าหมายเลขทั้งหมดจะอยู่ในการลงทะเบียนสำหรับหนึ่งรอบนาฬิกา

ตัวอย่างเช่นคุณสามารถจดบันทึก mod 5 ของค่าที่แต่ละบิตแทนเพิ่มเหล่านี้เข้าด้วยกันแล้วทำซ้ำกระบวนการจนกว่าคุณจะเหลืออะไรน้อยกว่า 5 ดำเนินการนี้ร่วมกันสำหรับขั้นตอนการลดทั้งหมด หรือใช้ตรรกะซ้ำสำหรับรอบจำนวนเล็กน้อย

แต่ถ้าคุณใช้ตัวดำเนินการ VHDL นั่นอาจเป็นคำตอบที่ถูก สมมติว่า บริษัท มีเครื่องมือการสังเคราะห์ที่เหมาะสมซึ่งจะช่วยให้คุณสามารถนำไปใช้งานได้อย่างมีประสิทธิภาพซึ่งอาจเป็นพื้นที่มากกว่าโซลูชันของเครื่องจักรบางที แต่ปริมาณงานเต็มที่และอาจเป็นพลังงานที่ดีต่อการคำนวณ มันเป็นตัวเลือกที่จะใช้เวลาน้อยที่สุดในการดำเนินการและดังนั้นจึงอาจเป็นเงินน้อยที่สุดสำหรับนายจ้าง!

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


3

หากจำนวนที่แสดงในหน่วยที่มีขนาดใหญ่กว่าหนึ่งบิตอาจเป็นประโยชน์ในการใช้การคำนวณแบบขนานบางอย่างเพื่อคำนวณ mod ของสารตกค้าง 15 โดยมีเงื่อนไขว่าการคำนวณอาจให้ 15 เป็นสิ่งที่เหลือหากเป็นศูนย์ วิธีง่าย ๆ ในการคำนวณ mod-15 ตกค้างคือการสังเกตว่าสำหรับค่าใด ๆ ของ N> = 1 การเพิ่มบิต 4N ซ้ายสุดไปยังส่วนของตัวเลขเกินกว่าที่จะให้ค่าซึ่งสอดคล้องกับ mod เดิม 15 นี้ อนุญาตให้แบ่งย่อยปัญหาได้หลายวิธีขึ้นอยู่กับทรัพยากรที่มี

ตัวอย่างเช่นหากหนึ่งเริ่มต้นด้วยค่า 32 บิตนั้นสามารถถือว่าเป็นค่าสี่ 4 บิต สิ่งเหล่านั้นอาจถูกรวมเข้าด้วยกันเป็นคู่ที่ชาญฉลาดเพื่อให้ได้ค่า 5 บิต 4 ค่าซึ่งสามารถรวมกันเป็นค่า 6 บิตสองค่าหรือค่า 7 บิตหนึ่งค่า การเพิ่มสามบิตด้านบนของค่า 7 บิตนั้นไปยัง 4 บิตด้านล่างจะให้ค่า 5 บิตซึ่งมีค่ามากที่สุด 21 ดังนั้นจึงสามารถกำหนดได้ว่าค่าดั้งเดิมนั้นมีค่าเท่ากับ 5 โดยการสังเกตว่าค่าสุดท้ายเป็นหรือไม่ หนึ่งใน 0, 5, 10, 15 หรือ 20


... หรือคุณสามารถใช้ตัวเสริมแบบ 4 บิตตลอดและตรวจสอบให้แน่ใจว่าการพกพาแต่ละอันจะกลายเป็นตัวพกพาสำหรับตัวบวกในภายหลังในวงจร หลังจากเพิ่มสามเลเยอร์คุณจะได้ผลลัพธ์ 4 บิตเดียวและมีการกระทำที่ไม่ได้ใช้สี่รายการ เพิ่มสามของการดำเนินการร่วมกันควบคู่ไปกับการเพิ่ม 4 บิตสุดท้ายและเพิ่มผลรวมของพวกเขาลงในผลลัพธ์ที่มีการดำเนินการล่าสุดเป็นแบบพกพา อัตราผลตอบแทนนี้มากที่สุด 19 ดังนั้นคุณไม่จำเป็นต้องจับคู่ในวันที่ 20 หลังจากนั้น
Henning Makholm

@HenningMakholm: มีหลายวิธีในการจัดเรียงตัวเพิ่มเพื่อให้ได้ผลลัพธ์ตามที่ต้องการ วิธีใดจะดีกว่าในสถานการณ์ที่กำหนดน่าจะขึ้นอยู่กับการกำหนดเส้นทางเฉพาะโครงการหรือปัญหาการใช้ทรัพยากร เคล็ดลับอีกประการหนึ่งคือการใช้เครื่องมือบันทึกการพกพา แต่ใช้ประโยชน์จากข้อเท็จจริงที่ว่าบิตบนสุดของเอาต์พุตที่เลื่อนอาจถูกย้ายไปด้านล่าง ดังนั้นหนึ่งเลเยอร์สามารถเปลี่ยนอินพุต 8 เป็น 6 จากนั้น 6 เป็น 4 จากนั้น 4 เป็น 3 และ 3 เป็น 2 เอาต์พุตหนึ่งเลเยอร์ของแต่ละเลเยอร์ก็จะเป็น AND ประตูและอีกหนึ่งประตูแฮคเกอร์ คู่ของค่า 4 บิตสำหรับ ...
supercat

... หนึ่งเดียวที่มีห่วงโซ่จะเป็นของสี่ประตูแฮคเกอร์ สำหรับว่ามันจะดีกว่าที่จะได้รับผลลัพธ์ที่ต่ำกว่า 19 หรือว่าจะดีกว่าที่จะตรวจสอบ 20 เป็นสารตกค้างที่เป็นไปได้ที่อาจขึ้นอยู่กับความพร้อมใช้งานของทรัพยากรและการใช้ประโยชน์ รับตัวเลขซึ่งไม่เกิน 30 การเพิ่ม nybbles ด้านบนและล่างจะให้ค่าที่มากที่สุด 15 (ทั้ง 16 + 14-> 1 + 14 หรือ 0 + 15-> 0 + 15) แต่เพิ่มอย่างชัดเจน การตรวจสอบบางส่วนหรือทั้งหมดของ (20, 25, 30) อาจถูกกว่า
supercat

2

ฉันจำ VHDL ของฉันไม่ได้ แต่นี่เป็นภาพร่างของความคิดที่นึกถึงก่อน:

ตัวเลขสุดท้าย (ในฐาน 10) ของพลังแรกของสองคือ 1, 2, 4, 8, 6, 2, ... และวัฏจักรซ้ำ ดังนั้นส่วนที่เหลือ mod 5 ของพลังของสองคือ 1, 2, 4, 3, ....

เมื่อใช้สิ่งนี้เราสามารถเลื่อนบิตจาก LSB และสะสมโมเดอเรเตอร์ที่เหลือ 5 ที่สอดคล้องกับตำแหน่งเมื่อ1เห็นบิต ทำการสะสม mod 5 ด้วยและก็เพียงพอที่จะตรวจสอบว่ายอดรวมเป็นศูนย์ที่สิ้นสุดหรือไม่


1

เราสามารถใช้ความคิดจากคำตอบตรงนี้ได้ว่าในฐาน 4 เราสามารถหาได้ว่าจำนวนหารด้วย 5 ได้ก็ต่อเมื่อผลรวมหลักเป็นทางเลือก ดังนั้นเรา

  1. จัดกลุ่มตัวเลข 2 ด้วย 2
  2. หาผลรวมของคี่และลบบล็อกคู่ 2 บิต
  3. หากผลลัพธ์อยู่ในส่วนเติมเต็มสองส่วนของบิตสองสามตัวอย่างเช่น [-4,3] (ง่ายต่อการตรวจสอบสมมติว่าเราใช้สองส่วนเติมเต็ม) จากนั้นเราจะเสร็จสิ้นและเราสามารถหารจำนวนเดิมด้วย 5 หากผลลัพธ์ของ ผลรวมคือ 0 ซึ่งเป็นนิพจน์ทางตรรกะที่ง่ายมากในการตรวจสอบ (โดยทั่วไปเป็นบิตขนาดใหญ่หรือบิตที่ได้ทั้งหมดไม่ใช่?)
  4. มิฉะนั้นเราจะทำซ้ำในจำนวนใหม่ (จำนวนที่สั้นกว่ามาก)

ให้เราลองเลข 166 = (10) (10) (01) (10): 2,2,1,2

2-2 + 1-2 = -1

ซึ่งคือ <= 3 ในค่าสัมบูรณ์และไม่ใช่ 0 ทำไมเราสามารถสรุปได้ในการวนซ้ำครั้งเดียวที่ 166 ไม่ได้หารด้วย 5 อย่างสม่ำเสมอ

อาจเป็นได้ว่าหน่วยความจำขนาดเล็กอาจมีราคาถูก / ดีกว่าในแง่ของความเร็ว / nr ของประตูมากกว่าการวนซ้ำ แน่นอนหนึ่งสามารถคำนวณล่วงหน้าที่เลวร้ายที่สุด (ผลลัพธ์ที่ใหญ่ที่สุดที่เป็นไปได้จากอินพุตที่อนุญาต) และวางแผนการออกแบบตามนั้น


1

วิธีการ MSB นั้นง่ายกว่า แต่ฉันจัดการทำแผนภาพสถานะ LSB โดยไม่จำเป็นต้องสร้างโซลูชัน MSB ... ใช้เวลาสองสามชั่วโมง มันจะเทียบเท่ากับที่แสดงโดย @ComFreek เพียงแค่ใส่คำอธิบายประกอบต่างกัน

เรากำลังจะติดตามตัวเลขสองตัว ก่อนอื่นเราจะติดตามผลรวมสะสมโมดูโล 5 ("SUM") ประการที่สองเราจะติดตามค่าของกำลังต่อไปของ 2 ที่จะเลื่อนเข้าโมดูโล 5 ("NEXT") ฉันจะเป็นตัวแทนของแต่ละรัฐด้วยค่าที่เป็นไปได้สำหรับ "SUM" ที่ด้านบนและค่า "NEXT" ที่สอดคล้องกันด้านล่าง

เราจะเริ่มด้วยกรณีที่ "SUM" modulo 5 เป็น 0:

แรกเริ่ม

โปรดทราบว่ารัฐที่มีลักษณะ:
3,2,4,1
1,4,3,2

เทียบเท่ากับ:
1,3,4,2
2,1,3,4

เนื่องจากสถานะทั้งสองแสดงว่า:
SUM = 1 และ NEXT = 4 OR
SUM = 2 และ NEXT = 3 หรือ
SUM = 3 และ NEXT = 2 หรือ
SUM = 4 และ NEXT = 1

โอเคดังนั้นตอนนี้เราจำเป็นต้องพัฒนารัฐพิเศษเนื่องจากผู้สัมภาษณ์ส่วนใหญ่จะไม่ประทับใจกับแผนภาพสถานะที่มีเพียงรัฐเดียว เราเสร็จสิ้นเมื่อทุกรัฐมีการเปลี่ยนสองครั้ง

เมื่อใดก็ตามที่คุณเปลี่ยนไปใช้สถานะใหม่แต่ละหมายเลขใน "NEXT" จะเพิ่มเป็นสองเท่าจากนั้นโมดูโลจะ 5 สำหรับ "SUM" ให้ทำตามกฎเหล่านี้:

  • หากคุณเปลี่ยนผ่านเป็น 0 แถวบนสุดจะเก็บค่าไว้
  • หากคุณเปลี่ยนไปเป็น 1 แต่ละคอลัมน์จะเป็นโมดูโล "SUM" + "NEXT" ของรัฐเก่า

ดังนั้นเรามาเริ่มต้นด้วยการกรอกทรานเซชั่นเมื่อบิตที่เข้ามาคือ 1

ทั้งหมด 1 รายการ

เอาล่ะตอนนี้เราเติมเลขศูนย์ มีเพียงหนึ่งสถานะที่เพิ่มเข้ามาดังนั้นเราจะดำเนินต่อไปและเติมเต็มช่วงการเปลี่ยนภาพเช่นกัน

สมบูรณ์

และ voila! เรามีเครื่องสถานะที่ยอมรับ LSB ก่อนโดยไม่ต้องสร้างโซลูชัน MSB


1

ทุกอย่างที่กล่าวมานั้นซับซ้อนมาก! มีวิธีการทางคณิตศาสตร์ที่ง่ายต่อการตรวจสอบว่าเป็นจำนวนเต็มไบนารีเป็นหารด้วยห้า ในการเริ่มต้นคุณจำวิธีทำ "การคัดออกเก้า" ในเลขทศนิยมปกติหรือไม่ กากโมดูโล่ 9 ของเลขจำนวนเต็มทศนิยมเหมือนกับโมดูโลตกค้าง 9 ของผลรวมของตัวเลข ใช้งานได้เพราะ 9 เป็นหนึ่งในจำนวนฐานที่น้อยกว่า

มีกระบวนการที่คล้ายกันคือ "การคัดเลือกลิฟท์" ซึ่งสัญญาณของตัวเลขอื่น ๆ จะถูกตั้งค่าเป็นลบ วิธีนี้ใช้งานได้เนื่องจาก 11 มีค่ามากกว่าฐานตัวเลข

ดังนั้นถ้าเราต้องการ "ขับไล่ห้าคน" เราอาจแทนจำนวนเต็มของเราในฐานสี่ จากนั้นเราเริ่มต้นด้วยตัวเลขหลักต่ำสุดเป็นผลรวมเริ่มต้นและลบออกจากตัวเลขสองหลักถัดไปเพื่อรับผลรวมถัดไป หลังจากผ่านจำนวนเต็มของผู้สมัครของเราด้วยวิธีนี้ผลรวมสุดท้ายจะเป็นศูนย์หรือหารด้วย 5 ถ้าจำนวนเต็มดั้งเดิมของเราหารด้วย 5

ตัวอย่าง 70: 01 00 01 10 -> 01 00 -1 -> 01 01 -> 00, หารด้วย 5 ตัวอย่าง 49: 11 00 01 -> 11 -1 -> 1 00 -> 1, ไม่ใช่ หารด้วย 5

โปรดทราบว่าคุณต้องมีบิตเพิ่มเติมสำหรับสัญลักษณ์ของความแตกต่างสะสมและสำหรับกรณีที่มีการดำเนินการ

อีกวิธีที่จะไปคือเพียงเพิ่มเลขฐานสิบหกเพื่อให้ได้โมดูโลตกค้างที่ 15 แน่นอนว่าคุณต้องมีขั้นตอนตรรกะขั้นสุดท้ายเพื่อระบุผลลัพธ์ที่ยอมรับได้สามศูนย์ห้าและสิบ

ตัวอย่าง 70: 4 6 -> A ดังนั้น 70 หารด้วย 5 (แต่ไม่ใช่ 15) ตัวอย่าง 49: 3 1 -> 4 ดังนั้น 70 ไม่หารด้วย 5

โปรดทราบว่าคุณสามารถใช้จำนวนฐานที่แตกต่างกันเพื่อสร้างการทดสอบการหารจำนวนมาก แต่ในตรรกะคอมพิวเตอร์นั้นค่ากำลังของ 2 +/- 1 นั้นง่ายที่สุดที่จะนำมาใช้

ในเลขทศนิยมทศนิยมหนึ่งในรายการโปรดของฉันคือการทดสอบของฉันสำหรับการตกค้าง mod 7 โปรดทราบว่า 100 เป็นสองมากกว่าทวีคูณของ 7 ดังนั้นกลุ่มตัวเลขเป็นคู่ (ทำงานในฐานจำนวน 100) และเพิ่มสองร้อยร้อยจากหน่วย ที่นี่เราทำงานจากซ้ายไปขวา ...

ตัวอย่าง: 98 76 -> 2 72 -> 76 ดังนั้น 9876 จึงไม่หารด้วย 7 มันคือ 6 mod 7 ตัวอย่าง: 03 45 67 -> 51 67 -> 1 69 -> 71 ดังนั้นมันจึงเป็น 1 mod 7

แน่นอนในไบนารีเพียงนำผลรวมของตัวเลขฐานแปด (กลุ่ม 3 บิต)

ขออภัยฉันหวังว่าฉันจะเป็นกูรู Verilog แต่เลขคณิตคือทั้งหมดที่ฉันสามารถให้ได้ในช่วงชีวิตนี้ ดู "Dead Reckoning" ของ Ron Doerfler สำหรับเทคนิคมากมายเช่นนี้


ฉันสงสัยว่าลูกพี่ลูกน้องแคนาดาของเราอาจมีอัลกอริทึมพิเศษบ้างไหม เนื่องจากพวกเขาจ่ายเงินเพนนีแคนาดาราคาทั้งหมดจะถูกปัดเศษเป็น $ 0.05 ที่ใกล้ที่สุด
richard1941

1

คำถามสัมภาษณ์ VHDL ควรส่งผลให้รหัส VHDL บางอย่าง

ฉันมีโอกาสพบข้อผิดพลาดแบ็กเอนด์ ghdl llvm ด้วยการใช้ตารางการเปลี่ยนสถานะของ Dave Tweed ที่ผู้เขียน ghdl กลั่นการใช้งานในฟังก์ชั่นถึง 17 บรรทัด:

type remains is (r0, r1, r2, r3, r4); -- remainder values

    function mod5 (dividend: bit_vector) return boolean is
        type remain_array is array (NBITS downto 0) of remains;
        type branch is array (remains, bit) of remains;
        constant br_table:  branch := ( r0 => ('0' => r0, '1' => r1),
                                        r1 => ('0' => r2, '1' => r3),
                                        r2 => ('0' => r4, '1' => r0),
                                        r3 => ('0' => r1, '1' => r2),
                                        r4 => ('0' => r3, '1' => r4)
                                      );
        variable  remaind:    remains := r0;
        variable tbit:        bit_vector (NBITS - 1 downto 0) := dividend;
    begin
        for i in dividend'length - 1 downto 0 loop
            remaind := br_table(remaind,tbit(i));
        end loop;
        return remaind = r0;
end function;

กรณีทดสอบที่เกี่ยวข้องนั้นมีขนาดค่อนข้างเล็กทำให้การดีบักง่ายขึ้นและใช้ชื่อรัฐที่เข้ากันได้กับ VHDL ในประเภทที่ระบุ

dave_tweed.png (สร้างด้วย Dia)

แนวคิดนี้ก็คือฟังก์ชั่น (หรือแม้แต่ตัวอย่างโปรแกรม VHDL 27 บรรทัด) นั้นสั้นพอที่จะเขียนคำตอบ VHDL ในระหว่างการสัมภาษณ์ ไม่จำเป็นต้องกังวลเกี่ยวกับการทำลายคำถามสัมภาษณ์ที่ต้องมีการสาธิตทั้งความรู้และทักษะผู้ให้สัมภาษณ์จะถูกคาดหวังให้ปกป้องการปฏิบัติเมื่อถูกสอบสวน

(ข้อผิดพลาดแบ็กเอนด์ llvm ได้รับการแก้ไขในการกระทำ1f5df6eก่อนหน้านี้ในวันนี้)

สิ่งหนึ่งที่ควรทราบคือตารางการเปลี่ยนสถานะยังบอกเราว่าบิตความฉลาดทางจะเป็น '1' ที่แสดงโดยการเปลี่ยนสถานะเป็นค่าที่เหลือน้อยกว่า (หรือการเปลี่ยนทั้งสองสำหรับ r4) เมื่อลบ 5 จากเงินปันผล ที่สามารถเข้ารหัสในตารางแยกต่างหาก (หรือตารางประเภทบันทึกซึ่งดูเหมือนว่ายุ่งยาก) เราทำสิ่งนี้ในอดีตเกี่ยวกับฮาร์ดแวร์กราฟิกที่เกี่ยวข้องกับความละเอียดหน้าจอแนวนอนที่ทวีคูณของ 5 พิกเซล

การทำเช่นนี้ทำให้ div / mod5 ผลิตความฉลาดและส่วนที่เหลือให้เรา:

library ieee;
use ieee.std_logic_1164.all;

entity divmod5 is
    generic (
        NBITS:  natural := 13 
    );
    port (
        clk:        in  std_logic;
        dividend:   in  std_logic_vector (NBITS - 1 downto 0);
        load:       in  std_logic;
        quotient:   out std_logic_vector (NBITS - 3 downto 0);
        remainder:  out std_logic_vector (2 downto 0);
        remzero:    out std_logic
    );
end entity;

architecture foo of divmod5 is
    type remains is (r0, r1, r2, r3, r4); -- remainder values
    type remain_array is array (NBITS downto 0) of remains;
    signal remaindr:    remain_array := (others => r0);
    signal dividendreg: std_logic_vector (NBITS - 1 downto 0);
    signal quot:        std_logic_vector (NBITS - 3 downto 0);
begin

parallel:
    for i in NBITS - 1 downto 0 generate
        type branch is array (remains, bit) of remains;
        -- Dave Tweeds state transition table:
        constant br_table:  branch := ( r0 => ('0' => r0, '1' => r1),
                                        r1 => ('0' => r2, '1' => r3),
                                        r2 => ('0' => r4, '1' => r0),
                                        r3 => ('0' => r1, '1' => r2),
                                        r4 => ('0' => r3, '1' => r4)
                                      );

        type qt is array (remains, bit) of std_ulogic;
    -- Generate quotient bits from Dave Tweeds state machine using q_table.
    -- A '1' when a remainder goes to a lower remainder or for both branches
    -- of r4. A '0' for all other branches.

        constant q_table:   qt :=     ( r0 => (others => '0'),
                                        r1 => (others => '0'),
                                        r2 => ('0' => '0', '1' => '1'),
                                        r3 => (others => '1'),
                                        r4 => (others => '1')
                                      );
        signal tbit:    bit;
    begin
        tbit <= to_bit(dividendreg(i));
        remaindr(i) <= br_table(remaindr(i + 1),tbit);
do_quotient:
        if i < quot'length generate   
            quot(i) <= q_table(remaindr(i + 1),tbit);
        end generate;
    end generate;

dividend_reg:
    process (clk)
    begin
        if rising_edge(clk) then
            if load = '1' then
                dividendreg <= dividend;
            end if;
        end if;
    end process;

quotient_reg:
    process (clk)
    begin
        if rising_edge (clk) then
            quotient <=  quot;
        end if;
    end process;

remainders:
    process (clk)
    begin
        if rising_edge(clk) then 
            remzero <= '0';
            case remaindr(0) is
                when r0 =>
                    remainder <= "000";
                    remzero <= '1';
                when r1 =>
                    remainder <= "001";
                when r2 =>
                    remainder <= "010";
                when r3 =>
                    remainder <= "011";
                when r4 =>
                    remainder <= "100";
            end case;
        end if;
    end process;

end architecture;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity divmod5_tb is
end entity;

architecture foo of divmod5_tb is
    constant NBITS:    integer range 0 to 13 := 8;
    signal clk:        std_logic := '0';
    signal dividend:   std_logic_vector (NBITS - 1 downto 0);
    signal load:       std_logic := '0';

    signal quotient:   std_logic_vector (NBITS - 3 downto 0);
    signal remainder:  std_logic_vector (2 downto 0);
    signal remzero:    std_logic;
    signal psample:    std_ulogic;
    signal sample:     std_ulogic;
    signal done:       boolean;
begin
DUT:
    entity work.divmod5
        generic map  (NBITS)
        port map (
            clk => clk,
            dividend => dividend,
            load => load,
            quotient => quotient,
            remainder => remainder,
            remzero => remzero
        );
CLOCK:
    process
    begin
        wait for 5 ns;
        clk <= not clk;
        if done'delayed(30 ns) then
            wait;
        end if;
    end process;
STIMULI:
    process
    begin
        for i in 0 to 2 ** NBITS - 1 loop
            wait for 10 ns;
            dividend <= std_logic_vector(to_unsigned(i,NBITS));
            wait for 10 ns;
            load <= '1';
            wait for 10 ns;
            load <= '0';
        end loop;
        wait for 15 ns;
        done <= true;
        wait;
    end process;

SAMPLER:
    process (clk)
    begin
        if rising_edge(clk) then
            psample <= load;
            sample <= psample after 4 ns;
        end if;
    end process;

MONITOR:
    process (sample)
        variable i:     integer;
        variable div5:  integer;
        variable rem5:  integer;
    begin
        if rising_edge (sample) then
            i := to_integer(unsigned(dividend));
            div5 := i / 5;
            assert div5 = unsigned(quotient)
                report LF & HT &
                    "i = " & integer'image(i) &
                    " div 5 expected " & integer'image(div5) & 
                    " got " & integer'image(to_integer(unsigned(quotient)))
                SEVERITY ERROR;
            rem5 := i mod 5;
            assert rem5 = unsigned(remainder)
                report LF & HT &
                    "i = " & integer'image(i) &
                    " rem 5 expected " & integer'image(rem5) & 
                    " got " & integer'image(to_integer(unsigned(remainder)))
                SEVERITY ERROR;
        end if;
    end process;

end architecture;

นำมาใช้ที่นี่พร้อมกับสร้างคำสั่งสร้างคำสั่งสร้างการผลิตบิตเชาวน์ อาร์เรย์ที่เหลือให้การติดตามการเปลี่ยนสถานะ:

divmod5_tb.png

ทั้งหมดนี้ไม่มีการดำเนินการทางคณิตศาสตร์

นอกจากนี้ยังเป็นไปได้ที่จะนำไปใช้ในกระบวนการโดยไม่ต้องลงทะเบียนทั้งหมดโดยใช้ประโยชน์จากพารามิเตอร์โดยไม่ต้องใช้โหมด นั่นจะเข้าใกล้จำนวนบรรทัดขั้นต่ำสำหรับการสัมภาษณ์

การติดตั้งตามลำดับแบบโอเวอร์คล็อกจะต้องใช้บิตตัวนับและการควบคุมการไหล (JK ฟล็อปฟล็อปและสองประตู)

มีการแลกเปลี่ยนเวลา / ความซับซ้อนขึ้นอยู่กับขนาดของเงินปันผลที่คุณอาจต้องได้รับในการสัมภาษณ์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.