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 and boxes on the rising edge where start is 1 and busy is 0. Hold busy high while you divide: 8 clock cycles, one quotient bit per clock cycle. Then pulse done for 1 cycle. Put the chocolates per box on quotient. Put the leftover count on remainder. Raise dbz together with done when the sampled boxes was 0.

Interface

PortDirectionTypeDescription
clkin1 bitClock
rstin1 bitSynchronous reset, active high
startin1 bitRequest a division
totalin8-bit unsignedChocolates in the batch (the dividend)
boxesin8-bit unsignedBoxes to fill (the divisor)
busyout1 bitHigh while a division is running
doneout1 bitHigh for 1 cycle when the result is ready
dbzout1 bitHigh with done when the sampled boxes was 0
quotientout8-bit unsignedChocolates per box
remainderout8-bit unsignedChocolates left over

Behavior

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

What the bench checks

  • busy and done are sampled every cycle of every job: 8 busy cycles, then a 1-cycle done pulse, never early, never late.
  • quotient, remainder, and dbz are checked while done is high, and checked as cleared to 0 after each reset.
  • One cycle after done, quotient, remainder, and dbz must still hold their checked values.
  • During every job's 8 busy cycles, dbz must stay low; it may rise only with done.
  • Results are compared against the true split for exact jobs, jobs with leftovers, total smaller than boxes, boxes of 1, and 255 at both ports.
  • A job where the compare lands exactly equal mid-run must still divide correctly.
  • Jobs with boxes of 0 must raise dbz with quotient 255 and remainder equal to total.
  • A start 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 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, and every output comes from a register. The bench reads outputs shortly after each edge.

SCOPE

this block only divides. The counter feeding total, the keypad behind boxes, 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.