Practice

Chocolate Box Splitter

A chocolate shop runs a small packing bench. After each batch, a counter shows how many chocolates came out, and the packer types in how many boxes the order needs. Until now the packers split each batch by eye. Boxes went out uneven, and a hotel client counted 11 chocolates in a box sold as 12.

Your task: build the divider block for the new panel. Sample total_i and boxes_i on the rising edge where start_i is 1 and busy_o is 0. Hold busy_o high while you divide: 8 clock cycles, one quotient bit per clock cycle. Then pulse done_o for 1 cycle. Put the chocolates per box on quotient_o. Put the leftover count on remainder_o. Raise dbz_o together with done_o when the sampled boxes_i was 0.

Interface

PortDirectionTypeDescription
clk_iin1 bitClock
rst_iin1 bitSynchronous reset, active high
start_iin1 bitRequest a division
total_iin8-bit unsignedChocolates in the batch (the dividend)
boxes_iin8-bit unsignedBoxes to fill (the divisor)
busy_oout1 bitHigh while a division is running
done_oout1 bitHigh for 1 cycle when the result is ready
dbz_oout1 bitHigh with done_o when the sampled boxes_i was 0
quotient_oout8-bit unsignedChocolates per box
remainder_oout8-bit unsignedChocolates left over

Behavior

  • A rising edge where start_i is 1 and busy_o is 0 accepts a job. total_i and boxes_i are sampled on that edge.
  • busy_o rises on the accepting edge and stays high for exactly 8 cycles. Each of those cycles produces one quotient bit.
  • busy_o falls and done_o rises on the same edge, 8 cycles after the accepting edge. done_o stays high for exactly 1 cycle.
  • While done_o is high: quotient_o holds total_i divided by boxes_i, rounded down. remainder_o holds the rest, so quotient_o * boxes_i + remainder_o = total_i.
  • If the sampled boxes_i is 0: quotient_o is 255, remainder_o equals the sampled total_i, and dbz_o rises with done_o, with the same timing.
  • dbz_o is 0 with done_o for every job whose sampled boxes_i was not 0.
  • dbz_o is 0 while busy_o is high: it rises, if at all, on the same edge as done_o.
  • After the done_o cycle, quotient_o, remainder_o, and dbz_o hold their values until the next accepted start_i or a reset.
  • start_i is ignored while busy_o is high. The running job keeps its sampled operands.
  • A new start_i is accepted on the edge that ends the done_o cycle, so jobs can run back to back.
  • rst_i high at a rising edge clears busy_o, done_o, dbz_o, quotient_o, and remainder_o on that same edge.

What the bench checks

  • busy_o and done_o are sampled every cycle of every job: 8 busy cycles, then a 1-cycle done_o pulse, never early, never late.
  • quotient_o, remainder_o, and dbz_o are checked while done_o is high, and checked as cleared to 0 after each reset.
  • One cycle after done_o, quotient_o, remainder_o, and dbz_o must still hold their checked values.
  • During every job's 8 busy cycles, dbz_o must stay low; it may rise only with done_o.
  • Results are compared against the true split for exact jobs, jobs with leftovers, total_i smaller than boxes_i, boxes_i of 1, and 255 at both ports.
  • A job where the compare lands exactly equal mid-run must still divide correctly.
  • Jobs with boxes_i of 0 must raise dbz_o with quotient_o 255 and remainder_o equal to total_i.
  • A start_i pulse with new operands in the middle of a run must not change the running job's result.
  • A second job started on the done_o cycle of the first must produce a correct result.
  • A 2-cycle mid-run reset is checked right after its first edge: a synchronous reset clears every output in 1 cycle.

Constraints

Build the division serially: shift, compare, subtract, one quotient bit per clock cycle. Do not use /, mod, rem, or % on the data path.

TIMING: everything is synchronous to the rising edge of clk_i, and every output comes from a register. The bench reads outputs shortly after each edge.

SCOPE: this block only divides. The counter feeding total_i, the keypad behind boxes_i, and the panel display are all out of scope.

Do not add ports.

Loading editor...

Click Run to execute your code. Output will appear here.