CodiodeCodiode
Home
Problem Solving
Skill Tracks
My Assignments
Contests
Leaderboard
Community
Settings
Codiode/Problems/Sequential Logic

Upstream vs Downstream Stall Backpressure

HardVerilog / SystemVerilogBuild

High-speed digital designs rely on pipelining to meet timing requirements, but downstream components like FIFOs or network MACs cannot always accept data every clock cycle. When a downstream receiver asserts a stall, the pipeline must pause to prevent dropping inflight data. A robust pipeline uses a valid/ready handshake to propagate this stall backwards combinationally, ensuring no data is overwritten while allowing bubbles (empty stages) to collapse and maximize throughput.

The module pipeline_backpressure implements a 3-stage pipeline with a complete valid/ready handshake. Data enters when i_valid and o_ready are both high, and exits when o_valid and i_ready are both high. Each of the three stages contains an 8-bit data register and a 1-bit valid register. A stage accepts new data if it is currently empty (its valid bit is 0) or if its downstream stage is ready to accept data. This creates a combinational backward path for the ready signal. If the downstream receiver drops i_ready while the pipeline is full, all stages must stall immediately. If the pipeline has empty stages, upstream stages will continue to accept data until all bubbles are filled.

Clock edge and reset behaviour: • Clock edge: posedge clk • Reset type: Asynchronous • Reset polarity: Active-low (rst_n) • Output values on reset: All internal valid registers and the output o_valid must clear to 0. All internal data registers and o_data must clear to 0. o_ready evaluates combinationally based on the reset state. • Priority rules: Reset takes priority over any valid/ready handshake.

Worked trace (Pipeline fill and stall): • Cycle 1: rst_n=0 → All stages empty. o_ready=1, o_valid=0. • Cycle 2: rst_n=1, i_valid=1, i_data=0xAA, i_ready=1 → Stage 1 accepts 0xAA. • Cycle 3: i_valid=1, i_data=0xBB, i_ready=0 → Stage 2 accepts 0xAA, Stage 1 accepts 0xBB. Stage 3 is empty, so Stage 2 is ready, making Stage 1 ready. o_ready=1. • Cycle 4: i_valid=1, i_data=0xCC, i_ready=0 → Stage 3 accepts 0xAA, Stage 2 accepts 0xBB, Stage 1 accepts 0xCC. Pipeline is now full. o_ready drops to 0 combinationally. • Cycle 5: i_valid=1, i_data=0xDD, i_ready=0 → o_ready=0, so 0xDD is not accepted. All stages hold their values. • Cycle 6: i_valid=0, i_data=0x00, i_ready=1 → Stage 3 outputs 0xAA. Stage 2's 0xBB moves to Stage 3. Stage 1's 0xCC moves to Stage 2. Stage 1 becomes empty. o_ready=1.

{ "signal": [
  { "name": "clk", "wave": "p......" },
  { "name": "rst_n", "wave": "0111111" },
  { "name": "i_valid", "wave": "0111100" },
  { "name": "i_data", "wave": "x======", "data": ["AA","BB","CC","DD","00","00"] },
  { "name": "i_ready", "wave": "0100011" },
  {},
  { "name": "o_ready", "wave": "1110011" },
  { "name": "o_valid", "wave": "0001110" },
  { "name": "o_data", "wave": "x..===x", "data": ["AA","AA","BB"] }
], "head": { "text": "Cycle-by-cycle pipeline fill and stall." } }

| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk | input | 1 | Positive-edge triggered clock | | rst_n | input | 1 | Asynchronous active-low reset; clears all valid flags and data to 0 | | i_valid | input | 1 | High when incoming i_data is valid | | i_data | input | 8 | Incoming data | | i_ready | input | 1 | High when downstream receiver can accept data | | o_valid | output | 1 | High when o_data is valid (Stage 3 valid flag) | | o_data | output | 8 | Outgoing data (Stage 3 data) | | o_ready | output | 1 | High when the pipeline can accept new data (Stage 1 ready flag) |

Constraints

  • The pipeline must have exactly three stages.
  • o_ready must be driven combinationally based on the valid state of the pipeline and i_ready.
  • o_valid and o_data must be registered outputs corresponding exactly to the third pipeline stage.
  • A stage must accept data if it is empty (its valid bit is 0) or if the immediately following stage is ready to accept data.
  • A valid pipeline stage holding data must not overwrite its contents if it accepts new data while stalled.

Topics

PipeliningHandshakeValid-ReadyBackpressure

Solve this problem

Write the module in Verilog, SystemVerilog or VHDL. Your submission is compiled and simulated against a real testbench — you get the waveform back, not a stored answer.

This problem is part of Codiode Pro. The statement above is free to read.

Sign in to solveSee what Pro unlocks

The circuit builder and code editor need a desktop screen. On a phone, read the problem here and open it on a laptop to solve.

Related problems

  • Basic D Flip FlopEasy
  • Debug: Missing Edge in Sensitivity ListMedium
  • Read After Write Hazard DetectionEasy
  • Parameterized Interface with ModportsHard
  • Struct Array PipelineHard
  • T Flip Flop from D Flip Flop TemplateEasy
  • Recursive Generate Reduction TreeHard
  • Four Stage Shift RegisterEasy

Browse all problems · Learning tracks