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
| Port | Direction | Type | Description |
|---|---|---|---|
clk_i | in | 1 bit | Clock |
rst_i | in | 1 bit | Synchronous reset, active high |
start_i | in | 1 bit | Request a division |
total_i | in | 8-bit unsigned | Chocolates in the batch (the dividend) |
boxes_i | in | 8-bit unsigned | Boxes to fill (the divisor) |
busy_o | out | 1 bit | High while a division is running |
done_o | out | 1 bit | High for 1 cycle when the result is ready |
dbz_o | out | 1 bit | High with done_o when the sampled boxes_i was 0 |
quotient_o | out | 8-bit unsigned | Chocolates per box |
remainder_o | out | 8-bit unsigned | Chocolates left over |
Behavior
- A rising edge where
start_iis 1 andbusy_ois 0 accepts a job.total_iandboxes_iare sampled on that edge. busy_orises on the accepting edge and stays high for exactly 8 cycles. Each of those cycles produces one quotient bit.busy_ofalls anddone_orises on the same edge, 8 cycles after the accepting edge.done_ostays high for exactly 1 cycle.- While
done_ois high:quotient_oholdstotal_idivided byboxes_i, rounded down.remainder_oholds the rest, soquotient_o * boxes_i + remainder_o = total_i. - If the sampled
boxes_iis 0:quotient_ois 255,remainder_oequals the sampledtotal_i, anddbz_orises withdone_o, with the same timing. dbz_ois 0 withdone_ofor every job whose sampledboxes_iwas not 0.dbz_ois 0 whilebusy_ois high: it rises, if at all, on the same edge asdone_o.- After the
done_ocycle,quotient_o,remainder_o, anddbz_ohold their values until the next acceptedstart_ior a reset. start_iis ignored whilebusy_ois high. The running job keeps its sampled operands.- A new
start_iis accepted on the edge that ends thedone_ocycle, so jobs can run back to back. rst_ihigh at a rising edge clearsbusy_o,done_o,dbz_o,quotient_o, andremainder_oon that same edge.
What the bench checks
busy_oanddone_oare sampled every cycle of every job: 8 busy cycles, then a 1-cycledone_opulse, never early, never late.quotient_o,remainder_o, anddbz_oare checked whiledone_ois high, and checked as cleared to 0 after each reset.- One cycle after
done_o,quotient_o,remainder_o, anddbz_omust still hold their checked values. - During every job's 8 busy cycles,
dbz_omust stay low; it may rise only withdone_o. - Results are compared against the true split for exact jobs, jobs with leftovers,
total_ismaller thanboxes_i,boxes_iof 1, and 255 at both ports. - A job where the compare lands exactly equal mid-run must still divide correctly.
- Jobs with
boxes_iof 0 must raisedbz_owithquotient_o255 andremainder_oequal tototal_i. - A
start_ipulse with new operands in the middle of a run must not change the running job's result. - A second job started on the
done_ocycle 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 behindboxes_i, and the panel display are all out of scope.
Do not add ports.
Click Run to execute your code. Output will appear here.