diff --git a/LICENSE-THIRD-PARTY.md b/LICENSE-THIRD-PARTY.md new file mode 100644 index 0000000..c29e9f5 --- /dev/null +++ b/LICENSE-THIRD-PARTY.md @@ -0,0 +1,17 @@ +# Third-Party Content Notice + +This repository contains references to external educational content from chipdev.io: + +- Problem descriptions and prompts for HDL design challenges +- Referenced under fair use for non-commercial, educational, and illustrative purposes +- Original content Β© chipdev.io – All rights reserved + +This repository is not affiliated with or endorsed by chipdev.io. +All problem statements remain the intellectual property of chipdev.io. + +--- + +The VHDL implementations, testbenches, and supporting infrastructure developed in this repository are licensed under: + +**GNU General Public License v3.0 (GPLv3)** +See the main [LICENSE](./LICENSE) file for details. diff --git a/README.md b/README.md index 692c57d..704c35e 100644 --- a/README.md +++ b/README.md @@ -122,10 +122,42 @@ These examples serve as a learning resource or starting point for building, simu 34. **Mealy Finite State Machine (FSM)** – 🟒 Easy – 🏒 Google, Microsoft - FSM where outputs depend on both current state and input. +## Implementation Notes + +> [!NOTE] +> **Deviations from ChipDev.io Specifications** +> +> This repository makes two consistent changes across all implementations: +> +> 1. **Reset signal naming**: ChipDev.io uses various names (`resetn`, `reset_n`, `reset`). This repository uniformly uses **`rst_n`** for consistency. +> +> 2. **Generic parameters**: Some quests specify hardcoded bit widths. This repository adds **`DATA_WIDTH`** and similar generic parameters where appropriate to improve reusability. +> +> Some signal names from the original problems (e.g., port naming conventions) may not be optimal but were preserved to maintain alignment with the source material. Quest-specific deviations are documented in individual README files. + +## Testbench Methodology + +> [!NOTE] +> **Professional Verification Approach** +> +> All testbenches follow industry-standard practices: +> +> - **VUnit framework**: Automated test execution with pass/fail reporting +> - **OSVVM RandomPkg**: Constrained-random stimulus generation for better coverage than sequential patterns +> - **Dual verification**: Checker procedures use different coding styles than the DUT to avoid systematic errors +> - **Edge case testing**: Explicit tests for boundary conditions, resets, and corner cases +> - **ModelSim .do files**: Pre-configured waveform views for debugging +> +> Test strategies typically include: +> +> 1. **Directed tests**: Exhaustive testing of all valid states/combinations +> 2. **Random tests**: Hundreds of randomized inputs to catch unexpected corner cases +> 3. **Reset testing**: Verify proper initialization and reset behavior + ## Minimum System Requirements - **OS**: (Anything that can run the following) - * **IDE**: + - **IDE**: - [`VSCode latest`](https://code.visualstudio.com/download) with following plugins: - [`Python`](https://marketplace.visualstudio.com/items?itemName=ms-python.python) by Microsoft - [`Pylance`](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) by Microsoft @@ -133,8 +165,8 @@ These examples serve as a learning resource or starting point for building, simu - [`Draw.io Integration: WaveDrom plugin`](https://marketplace.visualstudio.com/items?itemName=nopeslide.vscode-drawio-plugin-wavedrom) by nopeslide - [`TerosHDL`](https://marketplace.visualstudio.com/items?itemName=teros-technology.teroshdl) by Teros Technology - [`VHDL-LS`](https://marketplace.visualstudio.com/items?itemName=hbohlin.vhdl-ls) by Henrik Bohlin (Deactivate the one provided by TerosHDL) - * **VHDL Simulator**: (Anything that supports **VHDL-2008**): - * **Script execution environment**: + - **VHDL Simulator**: (Anything that supports **VHDL-2008**): + - **Script execution environment**: - `Python 3.11.4` to automatise testing via **VUnit** ## Initial Setup @@ -260,3 +292,17 @@ run_all_testbenches_lib( xunit_xml="./test/res.xml" # Output file for test results ) ``` + +## License + +All VHDL source code, testbenches, and scripts in this repository are licensed under the GNU General Public License v3.0 (GPLv3). +See the [LICENSE](./LICENSE) file for full details. + +> [!NOTE] +> Problem statements and task descriptions referenced from [chipdev.io](https://chipdev.io) are **not** part of this license. +> They are Β© chipdev.io and are used under fair use for educational purposes only. +> This repository is not affiliated with or endorsed by chipdev.io. +> This file and the accompanying VHDL code are licensed under GPLv3. + +> [!NOTE] +> See [LICENSE-THIRD-PARTY](./LICENSE-THIRD-PARTY.md) for more. diff --git a/ip/01_Simple_Router/README.md b/ip/01_Simple_Router/README.md new file mode 100644 index 0000000..08853f0 --- /dev/null +++ b/ip/01_Simple_Router/README.md @@ -0,0 +1,38 @@ +# Quest 1 - Simple Router + +## Original Problem Statement + +### Prompt + +Build a router circuit which forwards data from the input (din) to one of four outputs (dout0, dout1, dout2, or dout3), specified by the address input (addr). + +The address is a two bit value whose decimal representation determines which output value to use. Append to dout the decimal representation of addr to get the output signal name. For example, if addr=b11 then the decimal representation of addr is 3, so the output signal name is dout3. + +The input has an enable signal (din_en), which allows the input to be forwarded to an output when enabled. If an output is not currently being driven to, then it should be set to 0. + +### Input and Output Signals + +`din` - Input data +`din_en` - Enable signal for din. Forwards data from input to an output if 1, does not forward data otherwise +`addr` - Two bit destination address. For example addr = b11 = 3 indicates din should be forwarded to output value 3 (dout3) +`dout0` - Output 0. Corresponds to addr = b00 +`dout1` - Output 1. Corresponds to addr = b01 +`dout2` - Output 2. Corresponds to addr = b10 +`dout3` - Output 3. Corresponds to addr = b11 + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Combinational router using a `case` statement to decode the 2-bit address and route input data to one of four outputs. All outputs default to zero, then the selected output is conditionally assigned when `din_en` is high. Synthesises to a simple 4:1 demultiplexer with AND gates gating the enable signal. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/1). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/02_Second_Largest/README.md b/ip/02_Second_Largest/README.md new file mode 100644 index 0000000..1801a2e --- /dev/null +++ b/ip/02_Second_Largest/README.md @@ -0,0 +1,45 @@ +# Quest 2 – Second Largest + +## Original Problem Statement + +### Prompt + +Given a clocked sequence of unsigned values, output the second-largest value seen so far in the sequence. If only one value is seen, then the output (dout) should equal 0. Note that repeated values are treated as separate candidates for being the second largest value. + +When the reset-low signal (`resetn`) goes low, all previous values seen in the input sequence should no longer be considered for the calculation of the second largest value, and the output dout should restart from 0 on the next cycle. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous reset-low signal +`din` - Input data sequence +`dout` - Second-largest value seen so far + +### Output signals during reset + +`dout` - 0 when resetn is active + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Design a sequential circuit that monitors a stream of unsigned values and continuously outputs the **second-largest value** observed so far. If only a single value has been seen, then the output (`dout`) must remain `0`. + +Each value, even if repeated, should be treated as a distinct observation. That means duplicates are still valid inputs when determining the second largest. + +If the active-low reset (`resetn`) signal is asserted, any previously observed values must be discarded, and the calculation of the second-largest value starts fresh. In this reset state, `dout` should immediately return to `0`. + +--- + +## Source Reference + +This task is inspired by the "Second Largest" problem available at [chipdev.io](https://chipdev.io). +The description here has been paraphrased for clarity and adapted under fair use for educational and research purposes. + +Please refer to [LICENSE.third_party.md](../LICENSE.third_party.md) for licensing information. + +This quest is from [chipdev.io](https://chipdev.io/question/2). + +**Webarchive link:** diff --git a/ip/03_Rounding_Division/README.md b/ip/03_Rounding_Division/README.md new file mode 100644 index 0000000..7ede503 --- /dev/null +++ b/ip/03_Rounding_Division/README.md @@ -0,0 +1,32 @@ +# Quest 3 - Rounding Division + +## Original Problem Statement + +### Prompt + +Divide an input number by a power of two and round the result to the nearest integer. The power of two is calculated using 2^DIV_LOG2 where DIV_LOG2 is a module parameter. Remainders of 0.5 or greater should be rounded up to the nearest integer. If the output were to overflow, then the result should be saturated instead. + +### Input and Output Signals + +`din` - Input number +`dout` - Rounded result + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Divider that performs power-of-2 division with rounding. +The division is accomplished via right-shift by `DIV_LOG2` positions. +The rounding logic examines the bit at position `DIV_LOG2-1` (representing the 0.5 threshold) - if this bit is set, it adds 1 to the quotient. +The `resize()` function handles saturation when the result overflows the output width. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/3). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/04_Bit_Reverser/README.md b/ip/04_Bit_Reverser/README.md new file mode 100644 index 0000000..82130bd --- /dev/null +++ b/ip/04_Bit_Reverser/README.md @@ -0,0 +1,46 @@ +# Quest 4 - Gray Code Counter + +## Original Problem Statement + +### Prompt + +Build a circuit that generates a Gray code sequence starting from 0 on the output (dout). + +Gray code is an ordering of binary numbers such that two successive values only have one bit difference between them. For example, a Gray code sequence for a two bit value could be: + +b00 +b01 +b11 +b10 + +The Gray code sequence should use the standard encoding. In the standard encoding the least significant bit follows a repetitive pattern of 2 on, 2 off ( ... 11001100 ... ); the next digit a pattern of 4 on, 4 off ( ... 1111000011110000 ... ); the nth least significant bit a pattern of 2n on 2n off. + +When the reset-low signal (resetn) goes to 0, the Gray code sequence should restart from 0. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous reset-low signal +`out` - Gray code counter value + +### Output signals during reset + +`out` - 0 when resetn is active + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Combinational bit-reversal circuit using a loop that maps `dout(i) <= din(din'high - i)` to mirror the input vector. +Synthesises to pure wiring with no logic gates required. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/4). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/05_Gray_Code_Converter/README.md b/ip/05_Gray_Code_Converter/README.md new file mode 100644 index 0000000..67dbb5d --- /dev/null +++ b/ip/05_Gray_Code_Converter/README.md @@ -0,0 +1,31 @@ +# Quest 5 - Reversing Bits + +## Original Problem Statement + +### Prompt + +Reverse the bits of an input value's binary representation. + +### Input and Output Signals + +`din` - Input value +`dout` - Bitwise reversed value + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Sequential Gray code counter implemented as a binary counter with conversion output. +Each clock cycle increments a binary counter variable, then converts it to Gray code using the standard formula: `gray = count XOR shift_right(count, 1)`. +This produces the characteristic Gray code property where consecutive values differ by only one bit. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/5). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/06_Edge_Detector/README.md b/ip/06_Edge_Detector/README.md new file mode 100644 index 0000000..fcba3ef --- /dev/null +++ b/ip/06_Edge_Detector/README.md @@ -0,0 +1,38 @@ +# Quest 6 – Edge Detector + +## Original Problem Statement + +### Prompt + +Build a circuit that pulses `dout` one cycle after the rising edge of `din`. A pulse is defined as writing a single-cycle `1` as shown in the examples below. When `resetn` is asserted, the value of `din` should be treated as `0`. + +Bonus - can you enhance your design to pulse `dout` on the same cycle as the rising edge? Note that this enhancement will not pass our test suite, but is still a useful exercise. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous reset-low signal +`din` - Input signal +`dout` - Output signal + +### Output signals during reset + +`dout` - `0` when `resetn` is active + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Rising edge detector that registers the previous input value each clock cycle and outputs a single-cycle pulse when `din='1'` and differs from the registered value. +The comparison `din /= din_reg` detects the transition, while the `din = '1'` check ensures it's specifically a rising edge. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/6). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/07_Serialiser/README.md b/ip/07_Serialiser/README.md new file mode 100644 index 0000000..f0870fa --- /dev/null +++ b/ip/07_Serialiser/README.md @@ -0,0 +1,49 @@ +# Quest 7 – Serialiser + +## Original Problem Statement + +### Prompt + +Build a circuit that takes the multi-bit input (`din`) and shifts the input value's least significant bit (rightmost bit) to the single-bit output (`dout`) one bit at a time. + +The circuit should begin shifting the input's least significant bit when the the input enable signal (`din_en`) goes high. In other words, the input enable signal going high indicates that this circuit should start shifting the current input signal from it's least significant bit, regardless of which bits the circuit has already shifted. + +If all the input's bits have been shifted to the output so that there are no more bits to shift, the output must output `0`. + +When reset (`resetn`) is active, the input value that is being shifted is treated as `0`. Even when reset goes back to being inactive, the input value will still be treated as `0`, unless the input enable signal makes the circuit begin shifting from the input again. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous reset-low signal +`din` - Input signal +`din_en` - Enable signal for input data +`dout` - Output signal + +### Output signals during reset + +`dout` - `0` when `resetn` is active + +> [!NOTE] +> For the complete problem description, please visit: +> + +> [!NOTE] +> **Implementation Deviation** +> +> This implementation adds a `DATA_WIDTH` generic parameter for configurability, though the original problem doesn't specify a particular bit width. + +## Description + +Serializer that captures a parallel input word when `din_en` asserts and shifts it out LSB-first over subsequent clock cycles. +A `bit_index` counter tracks which bit to output, incrementing from 0 to `DATA_WIDTH-1`. +The captured data remains in `din_reg` until the entire word is transmitted, then zeros out. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/7). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/08_Deserialiser/README.md b/ip/08_Deserialiser/README.md new file mode 100644 index 0000000..9dabff0 --- /dev/null +++ b/ip/08_Deserialiser/README.md @@ -0,0 +1,44 @@ +# Quest 8 – Deserialiser + +## Original Problem Statement + +### Prompt + +Build a circuit that reads a sequence of bits (one bit per clock cycle) from the input (`din`), and shifts the bits into the least significant bit of the output (`dout`). Assume all bits of the output are `0` to begin with. + +Once the number of input bits received is larger than `DATA_WIDTH`, only the `DATA_WIDTH` most recent bits are kept in the output. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous reset-low signal +`din` - Input signal +`dout` - Output signal + +### Output signals during reset + +`dout` - `0` when `resetn` is active + +> [!NOTE] +> For the complete problem description, please visit: +> + +> [!NOTE] +> **Implementation Deviation** +> +> This implementation adds a `DATA_WIDTH` generic parameter for configurability, though the original problem doesn't specify a particular bit width. + +## Description + +Deserialiser that reconstructs a parallel word from serial input. +Each clock cycle shifts the output register left and inserts the new `din` bit at the LSB position using the concatenation `dout <= dout(dout'high - 1 downto 0) & din`. +After `DATA_WIDTH` clock cycles, the complete word appears at the output. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/8). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/09_Fibonacci_Generator/README.md b/ip/09_Fibonacci_Generator/README.md new file mode 100644 index 0000000..0b27831 --- /dev/null +++ b/ip/09_Fibonacci_Generator/README.md @@ -0,0 +1,51 @@ +# Quest 9 – Fibonacci Generator + +## Original Problem Statement + +### Prompt + +Design a circuit which generates the Fibonacci sequence starting with `1` and `1` as the first two numbers. + +The Fibonacci sequence is a sequence of numbers where each number is the sum of the two previous numbers. More formally this can be expressed as: + +`Fβ‚€ = 1` +`F₁ = 1` +`Fβ‚™ = Fₙ₋₁ + Fβ‚™β‚‹β‚‚ for n > 1`. + +Following the definition of the Fibonacci sequence above we can see that the sequence is `1, 1, 2, 3, 5, 8, 13, etc`. + +The sequence should be produced when the active low signal (`resetn`) becomes active. In other words, the sequence should restart from `1` followed by another `1` (the Fibonacci sequence's initial condition) as soon as `resetn` becomes active. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous reset-low signal +`out` - Current Fibonacci number + +### Output signals during reset + +`out` - `1` when `resetn` is active (the first `1` of the Fibonacci sequence) + +> [!NOTE] +> For the complete problem description, please visit: +> + +> [!NOTE] +> **Implementation Deviation** +> +> This implementation adds a `DATA_WIDTH` generic parameter for configurability and overflow handling, though the original problem doesn't specify a particular bit width. + +## Description + +Fibonacci sequence generator using a 2-element pipeline holding the previous two values. +Each clock cycle computes `sum = fib[1] + fib[0]`, then shifts the pipeline left, discarding the oldest value and inserting the new sum. +The pipeline initialises to `[1, 1]` and produces the sequence 1, 1, 2, 3, 5, 8, 13... + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/9). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/10_Counting_Ones/README.md b/ip/10_Counting_Ones/README.md new file mode 100644 index 0000000..bb7a8f6 --- /dev/null +++ b/ip/10_Counting_Ones/README.md @@ -0,0 +1,31 @@ +# Quest 10 – Counting Ones + +## Original Problem Statement + +### Prompt + +Given an input binary value, output the number of bits that are equal to `1`. + +### Input and Output Signals + +`din` - Input value +`dout` - Number of `1`'s in the input value + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Population count (popcount) circuit that returns the number of '1' bits in the input vector. +Implemented using the `get_amount_of_state()` utility function from the utils package which counts occurrences of a specified bit state. +The output width is `ceil(log2(DATA_WIDTH))` bits to accommodate the maximum possible count. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/10). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/11_Gray_Code_to_Binary/README.md b/ip/11_Gray_Code_to_Binary/README.md new file mode 100644 index 0000000..f831ab5 --- /dev/null +++ b/ip/11_Gray_Code_to_Binary/README.md @@ -0,0 +1,36 @@ +# Quest 11 – Gray Code to Binary + +## Original Problem Statement + +### Prompt + +Given a value, output its index in the standard Gray code sequence. This is known as converting a Gray code value to binary. + +Each input value's binary representation is an element in the Gray code sequence, and your circuit should output the index of the Gray code sequence the input value corresponds to. + +In the standard encoding the least significant bit follows a repetitive pattern of 2 on, 2 off ( `... 11001100 ...` ); the next digit a pattern of 4 on, 4 off ( `... 1111000011110000 ...` ); the nth least significant bit a pattern of 2ⁿ on 2ⁿ off. + +### Input and Output Signals + +`gray` - Input signal, interpreted as an element of the Gray code sequence +`bin` - Index of the Gray code sequence the input corresponds to + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Gray-to-binary decoder using iterative XOR reduction. +Starting with the Gray code input, it repeatedly XORs the current value with itself right-shifted by 1, accumulating the result. +The loop continues until the mask (shifted value) becomes zero. +This implements the standard conversion where each binary bit equals the XOR of all Gray code bits from that position to the MSB. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/11). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/12_Trailing_Zeroes/README.md b/ip/12_Trailing_Zeroes/README.md new file mode 100644 index 0000000..c3203d7 --- /dev/null +++ b/ip/12_Trailing_Zeroes/README.md @@ -0,0 +1,31 @@ +# Quest 12 – Trailing Zeroes + +## Original Problem Statement + +### Prompt + +Find the number of trailing `0`s in the binary representation of the input (`din`). If the input value is all `0`s, the number of trailing `0`s is the data width (`DATA_WIDTH`) + +### Input and Output Signals + +`din` - Input value +`dout` - Number of trailing `0`s + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Counts consecutive zero bits starting from the LSB. +Uses the `get_amount_of_trailing_state()` utility function to identify how many zeros appear before the first '1' bit. +The output width includes an extra bit (`to_bits(DATA_WIDTH) + 1`) to represent the case where all bits are zero. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/12). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/13_One_Hot_Detector/README.md b/ip/13_One_Hot_Detector/README.md new file mode 100644 index 0000000..c7b7f0c --- /dev/null +++ b/ip/13_One_Hot_Detector/README.md @@ -0,0 +1,31 @@ +# Quest 13 – One-Hot Detector + +## Original Problem Statement + +### Prompt + +One-hot values have a single bit that is a `1` with all other bits being `0`. Output a `1` if the input (`din`) is a one-hot value, and output a `0` otherwise. + +### Input and Output Signals + +`din` - Input value +`onehot` - `1` if the input is a one-hot value and `0` otherwise + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Validates one-hot encoding by checking if exactly one bit is set. +Uses the `is_one_hot()` utility function which returns true only when the input contains a single '1' bit with all others '0'. +Common in FSM state encodings and bus arbitration where mutual exclusion is required. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/13). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/14_Stopwatch_Timer/README.md b/ip/14_Stopwatch_Timer/README.md new file mode 100644 index 0000000..23e6f5c --- /dev/null +++ b/ip/14_Stopwatch_Timer/README.md @@ -0,0 +1,45 @@ +# Quest 14 – Stopwatch Timer + +## Original Problem Statement + +### Prompt + +Build a module which controls a stopwatch timer. + +The timer starts counting when the start button (`start`) is pressed (pulses) and increases by `1` every clock cycle. When the stop button (`stop`) is pressed, the timer stops counting. When the reset button (`reset`) is pressed, the count resets to `0` and the timer stops counting. + +If count ever reaches `MAX`, then it restarts from `0` on the next cycle. + +`stop`'s functionality takes priority over `start`'s functionality, and `reset`'s functionality takes priority over both `stop` and `start`'s functionality. + +### Input and Output Signals + +`clk` - Clock signal +`reset` - Synchronous reset signal +`start` - Start signal +`stop` - Stop signal +`count` - Current count + +### Output signals during reset + +`count` - `0` when `reset` is active + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Stopwatch counter that starts/stops via control signals and counts from `0 to MAX`. +The `start_reg` variable latches the start condition, continuing the count until `stop_in` resets it. +When the counter reaches MAX, it wraps to zero. +The start signal acts as a sticky enable - once asserted, counting continues autonomously until explicitly stopped. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/14). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/15_Sequence_Detector/README.md b/ip/15_Sequence_Detector/README.md new file mode 100644 index 0000000..fcefcf5 --- /dev/null +++ b/ip/15_Sequence_Detector/README.md @@ -0,0 +1,39 @@ +# Quest 15 – Sequence Detector + +## Original Problem Statement + +### Prompt + +Given a stream of input bits, pulse a `1` on the output (`dout`) whenever a `b1010` sequence is detected on the input (`din`). + +When the reset-low signal (`resetn`) goes active, all previously seen bits on the input are no longer considered when searching for `b1010`. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous reset-low signal +`din` - Input bits +`dout` - `1` if a `b1010` was detected, `0` otherwise + +### Output signals during reset + +`dout` - `0` when `resetn` is active + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Parameterizable sequence detector using a shift register matched against a constant pattern. +Each clock shifts the serial input `din` into the register, with the code handling both ascending and descending bit orderings via compile-time selection. +Detection pulses high when the shift register contents exactly match `SEQUENCE_PATTERN`. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/15). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/16_Divisible_by_3/README.md b/ip/16_Divisible_by_3/README.md new file mode 100644 index 0000000..4ef0f8d --- /dev/null +++ b/ip/16_Divisible_by_3/README.md @@ -0,0 +1,44 @@ +# Quest 16 – Divisible by 3 + +## Original Problem Statement + +### Prompt + +Design a circuit that determines whether an input value is evenly divisible by three. + +The input value is of unknown length and is left-shifted one bit at a time into the circuit via the input (`din`). The circuit should output a `1` on the output (`dout`) if the current cumulative value is evenly divisible by three, and a `0` otherwise. + +When `resetn` is asserted, all previous bits seen on the input are no longer considered. The `0` seen during reset should not be included when calculating the next value. + +This problem is tricky, so it may help to think in terms of modulus and remainder states. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous reset-low signal +`din` - Input bit +`dout` - `1` if the current value is divisible by `3`, `0` otherwise + +### Output signals during reset + +`dout` - `0` when `resetn` is asserted + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Bitwise divisibility-by-3 detector using modular arithmetic FSM. +Exploits the property that powers of 2 modulo 3 alternate between 1 and 2 (2^0≑1, 2^1≑2, 2^2≑1...). +The state machine tracks remainder {0,1,2} as each bit arrives, with state transitions encoding how each bit contributes to the running modulo-3 sum. +Divisible when final state is `rem_0`. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/16). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/17_Divisible_by_5/README.md b/ip/17_Divisible_by_5/README.md new file mode 100644 index 0000000..27f51fb --- /dev/null +++ b/ip/17_Divisible_by_5/README.md @@ -0,0 +1,44 @@ +# Quest 17 – Divisible by 5 + +## Original Problem Statement + +### Prompt + +Design a module that determines whether an input value is evenly divisible by five. + +The input value is of unknown length and is left-shifted one bit at a time into the module via the input (`din`). The module should output a `1` on the output (`dout`) if the current cumulative value is evenly divisible by five and a `0` otherwise. + +When `resetn` is asserted, all previous bits seen on the input are no longer considered. The `0` seen during reset should not be included when calculating the next value. + +This problem is tricky, so it may help to think in terms of modulus and remainder states. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous reset-low signal +`din` - Input bit +`dout` - `1` if the current value is divisible by `5`, `0` otherwise + +### Output signals during reset + +`dout` - `0` when `resetn` is active + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Bitwise divisibility-by-5 detector using modular arithmetic FSM. +Powers of 2 modulo 5 cycle as {1,2,4,3,1...}, which the state machine tracks across five remainder states {0,1,2,3,4}. +Each input bit transitions the state according to its positional contribution modulo 5. +Divisible when final state is `rem_0`. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/17). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/18_Palindrome_Detector/README.md b/ip/18_Palindrome_Detector/README.md new file mode 100644 index 0000000..320dd85 --- /dev/null +++ b/ip/18_Palindrome_Detector/README.md @@ -0,0 +1,32 @@ +# Quest 18 – Palindrome Detector + +## Original Problem Statement + +### Prompt + +Given an input (`din`), output (`dout`) a `1` if its binary representation is a palindrome and a `0` otherwise. + +A palindrome binary representation means that the binary representation has the same sequence of bits whether you read it from left to right or right to left. Leading `0`s are considered part of the input binary representation. + +### Input and Output Signals + +`din` - Input value +`dout` - `1` if the binary representation is a palindrome, `0` otherwise + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Palindrome detector that reverses the input vector via a generate loop assigning `din_reversed(i) <= din(i)` with reversed range declaration. +The equality comparison `din = din_reversed` then determines if the bit pattern is symmetric. Pure combinational logic. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/18). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/19_Programmable_Sequence_Detector/README.md b/ip/19_Programmable_Sequence_Detector/README.md new file mode 100644 index 0000000..60ea997 --- /dev/null +++ b/ip/19_Programmable_Sequence_Detector/README.md @@ -0,0 +1,42 @@ +# Quest 19 – Programmable Sequence Detector + +## Original Problem Statement + +### Prompt + +Given a stream of input bits, pulse a `1` on the output (`seen`) whenever a specified 5-bit target sequence is detected on the input (`din`). The target sequence is specified by `init` and is updated whenever the reset-low signal (`resetn`) is deasserted. + +The target sequence is always a 5-bit value, so left-padded `0`'s are also considered part of the sequence (a sequence specified as `b11` would actually be `b00011`). + +When `resetn` goes active, all previously seen bits on the input are no longer considered when searching for the target sequence. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous reset-low signal +`init` - Target sequence to detect. Updated whenever `resetn` is asserted +`din` - Input bits +`seen` - `1` if the sequence specified by `init` was detected, `0` otherwise + +### Output signals during reset + +`seen` - `0` when `resetn` is active + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Run-time programmable sequence detector that captures the target pattern from `init` during reset. +A shift register accumulates incoming bits while `din_count` tracks how many bits have been received. +The `seen` output asserts only after exactly `DATA_WIDTH` bits have been collected and the shift register matches the programmed pattern. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/19). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/20_Divide_by_Evens_Clock_Divider/README.md b/ip/20_Divide_by_Evens_Clock_Divider/README.md new file mode 100644 index 0000000..571bd80 --- /dev/null +++ b/ip/20_Divide_by_Evens_Clock_Divider/README.md @@ -0,0 +1,42 @@ +# Quest 20 – Divide-by-Evens Clock Divider + +## Original Problem Statement + +### Prompt + +Given an input clock signal, generate three output clock signals with 2x, 4x, and 6x the period of the input clock. + +When `resetn` is active, then all clocks are reset to `0`. When `resetn` becomes inactive again, all clocks should undergo their posedge transition and start an entirely new clock period. Specifically this means that if `resetn` became active in the middle of an output clock's period, when `resetn` becomes inactive the output clock should start an entirely new period instead of continuing from where the interrupted period left off. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous reset-low signal +`div2` - Output clock with 2x the period of `clk` +`div4` - Output clock with 4x the period of `clk` +`div6` - Output clock with 6x the period of `clk` + +### Output signals during reset + +`div2` - `0` when `resetn` is active +`div4` - `0` when `resetn` is active +`div6` - `0` when `resetn` is active + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Multiple clock divider generating divide-by-2, divide-by-4, and divide-by-6 outputs. +The divide-by-2 simply toggles each clock. Divide-by-4 and divide-by-6 use counters that toggle their outputs every N/2 clocks (where N is the division factor). +This produces 50% duty cycle divided clocks for even division ratios. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/20). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/21_FizzBuzz/README.md b/ip/21_FizzBuzz/README.md new file mode 100644 index 0000000..be3a912 --- /dev/null +++ b/ip/21_FizzBuzz/README.md @@ -0,0 +1,46 @@ +# Quest 21 – FizzBuzz + +## Original Problem Statement + +### Prompt + +Design a circuit that counts incrementally for a maximum number of cycles, `MAX_CYCLES`. At all cycles, the circuit should determine whether or not the counter value is evenly divisible by parameters `FIZZ`, `BUZZ`, or both. + +The counter value should monotonically increase when the reset signal (`resetn`) is de-asserted. The counter sequence is expected to start from 0 and be `MAX_CYCLES` long, restarting from 0 when `MAX_CYCLES` is reached (e.g. for `MAX_CYCLES = 100: 0, 1, 2, 3, ..., 99, 0, 1, ...`). + +As the circuit counts, output `fizz` should be asserted if the current counter value is evenly divisible by `FIZZ`. `buzz` should output 1 when the current counter value is divisible by `BUZZ`. Finally, output `fizzbuzz` should be 1 when counter is evenly divisible by both `FIZZ` and `BUZZ`. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous, active low, reset signal +`fizz` - Output Fizz +`buzz` - Output Buzz +`fizzbuzz` - Output FizzBuzz + +### Output signals during reset + +`fizz` - 1 +`buzz` - 1 +`fizzbuzz` - 1 + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Hardware FizzBuzz counter with independent modulo counters for fizz (mod 3) and buzz (mod 5). +Each counter increments independently and wraps when reaching its maximum. +The `fizz` and `buzz` outputs pulse high when their respective counters wrap. +`fizzbuzz` is the logical AND of both, pulsing when divisible by both 3 and 5 (i.e., divisible by 15). +A master `cycle_count` resets all counters after `MAX_CYCLES`. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/21). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/22_Full_Adder/README.md b/ip/22_Full_Adder/README.md new file mode 100644 index 0000000..d40b0db --- /dev/null +++ b/ip/22_Full_Adder/README.md @@ -0,0 +1,38 @@ +# Quest 22 – Full Adder + +## Original Problem Statement + +### Prompt + +Design a Full Adder (FA)β€”the most important building block for digital computation. + +A FA is a fully combinational circuit that adds three single-bit inputs `a`, `b`, and `cin` (carry-in). Inputs `a` and `b` are the two operands whereas `cin` represents the overflow bit carried forward from a previous addition stage. + +The FA circuit has two single-bit outputs, `sum` and `cout`β€”the later represents the overflow bit to be used as a carry-in to a subsequent addition stage. + +### Input and Output Signals + +`a` - First operand input bit +`b` - Second operand input bit +`cin` - Carry-in input bit from a previous adder stage +`sum` - Sum output bit +`cout` - Carry-out (overflow) output bit to be propagated to the next addition stage + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Full adder with two architectural implementations. +The gate-level version uses the canonical equations: `sum = a XOR b XOR cin` and `cout = (a AND b) OR (b AND cin) OR (cin AND a)`. +The operator-based version performs unsigned addition across three separate 2-bit additions with carry propagation. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/22). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/23_Basic_ALU/README.md b/ip/23_Basic_ALU/README.md new file mode 100644 index 0000000..d89ff41 --- /dev/null +++ b/ip/23_Basic_ALU/README.md @@ -0,0 +1,39 @@ +# Quest 23 – Basic ALU + +## Original Problem Statement + +### Prompt + +Design a simple Arithmetic Logic Unit (ALU) which performs a set of operations on two input operands `a` and `b`. The outputs of each operation are sent to the corresponding output signal - `a_plus_b`, `a_minus_b`, `not_a`, `a_and_b`, `a_or_b`, and `a_xor_b`. + +The ALU is an important part of many modern computing systems. Conventional ALUs receive two operands from an external control unit, as well as an opcode which determines the type of calculation to perform. For this question, we've simplified the behavior such that the ALU produces all outputs at once. + +### Input and Output Signals + +`a` - First operand input +`b` - Second operand input +`a_plus_b` - Output `a` plus `b` +`a_minus_b` - Output `a` minus `b` +`not_a` - Output not `a` (ones complement) +`a_and_b` - Output `a` bitwise-and `b` +`a_or_b` - Output `a` bitwise-or `b` +`a_xor_b` - Output `a` exclusive-or `b` + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Combinational ALU providing six parallel operations: addition, subtraction, NOT, AND, OR, and XOR. +All operations compute concurrently on the same inputs with results appearing at separate output ports. +The `resize()` function handles overflow saturation for arithmetic operations. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/23). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/24_Ripple_Carry_Adder/README.md b/ip/24_Ripple_Carry_Adder/README.md new file mode 100644 index 0000000..b4ab823 --- /dev/null +++ b/ip/24_Ripple_Carry_Adder/README.md @@ -0,0 +1,38 @@ +# Quest 24 – Ripple Carry Adder + +## Original Problem Statement + +### Prompt + +A Ripple Carry Adder (RCA) is a multi-bit addition circuit composed of a number of cascaded full adders (FAs). In an RCA, the carry-out bit of stage i is propagated to the carry-in port, `cin`, of stage i+1 so that the carry bit ripples through the entire chain of FAs, from the least significant bit (LSB) to the most significant bit (MSB). + +Use the solution to question 22 (Full Adder) and implement a flexible data width RCA. The RCA module takes two integers `a` and `b`, and produces two output words `sum` and `cout_fa1`. Output `cout_fa1` corresponds to the carry-out nets of each FA stage. + +Important: This question must be solved using a multimodule approach. That is, there must be a module for a single-bit FA that is instantiated `DATA_WIDTH` times in order to build a multi-bit RCA. You will be able to use the solution to question 22 (Full Adder) as the single-bit FA module. + +### Input and Output Signals + +`a` - First operand input word +`b` - Second operand input word +`sum` - Output word corresponding to a plus b operation (note that sum has DATA_WIDTH+1 bits to account for the carry-out/overflow bit) +`cout_int` - Internal carry-out nets, ouputs of the full adder instances + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Ripple-carry adder built from a chain of full adder instances. +A generate loop instantiates DATA_WIDTH full adders, with each stage's carry-out feeding the next stage's carry-in. +The first stage uses the external `cin` input. +Exposes internal carry signals via `cout_int` for use in advanced adder topologies like carry-select adders. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/24). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/25_Flip_Flop_Array/README.md b/ip/25_Flip_Flop_Array/README.md new file mode 100644 index 0000000..44a4607 --- /dev/null +++ b/ip/25_Flip_Flop_Array/README.md @@ -0,0 +1,47 @@ +# Quest 25 – Flip-Flop Array + +## Original Problem Statement + +### Prompt + +Design a simple 1-read/write (1RW) register file (RF) by using a multidimentional array of flip-flops in Verilog. + +The RF should have 8 entries with each entry being an 8-bit digital word. The input word `din` is written to one of the 8 entries of the RF by using the 3-bit port `addr` and asserting signal `wr`. An entry is retrieved from the RF by selecting the address and asserting the `rd` signal. If one tries to read from an address that has never been written to, then `dout` and `error` should both output zero. + +This is a simple RF so it should support only one operation per clock cycle, either a read or write. If both `rd` and `wr` ports are set to logic level high in a cycle, then `error` is asserted, and `dout` is set to zero in order to indicate the operation has failed. + +### Input and Output Signals + +`din` - Input data port +`addr` - Address input to the flip-flop array +`wr` - Write-enable input signal +`rd` - Read-enable input signal +`clk` - Clock signal +`resetn` - Synchronous, active-low, reset signal +`dout` - Output data port +`error` - Error signal - Invalid operation + +### Output signals during reset + +`dout` - 0 +`error` - 0 + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Single-port memory array using flip-flops rather than RAM primitives. +Implements `2^ADDRESS_WIDTH` locations of DATA_WIDTH bits each using a process variable array. +The `wr` and `rd` signals must be mutually exclusive - simultaneous assertion triggers the `error` output. +Read operations are synchronous with registered outputs. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/25). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/25_Flip_Flop_Array/tb_flip_flop_array.vhd b/ip/25_Flip_Flop_Array/tb_flip_flop_array.vhd index aa1d6cd..7f6165b 100644 --- a/ip/25_Flip_Flop_Array/tb_flip_flop_array.vhd +++ b/ip/25_Flip_Flop_Array/tb_flip_flop_array.vhd @@ -47,9 +47,9 @@ architecture tb of tb_flip_flop_array is begin generate_clock(clk => clk, FREQ => real(1 sec / CLK_PERIOD)); - ------------------------------------------------------------ + ------------------------------------------------------------ -- VUnit - ------------------------------------------------------------ + ------------------------------------------------------------ test_runner_watchdog(runner, SIM_TIMEOUT); main: process @@ -66,7 +66,7 @@ begin test_runner_cleanup(runner); wait; end process; - + checker: process constant PROPAGATION_TIME: time := 1 ns; @@ -197,13 +197,13 @@ begin 11 => 0, -- Write again to address 0 12 => 1, -- Read from address 1 (shouldn't change) 13 => 0, -- Read from address 0 (should be changed) - 14 => 7, -- - 15 => 7, -- - 16 => 255, -- - 17 => 255, -- - 18 => 10, -- - 19 => 10, -- - 20 => 0 -- + 14 => 7, -- + 15 => 7, -- + 16 => 255, -- + 17 => 255, -- + 18 => 10, -- + 19 => 10, -- + 20 => 0 -- ); constant DIN_SEQUENCE: integer_vector := ( 0 => 16#00#, -- Reset @@ -258,7 +258,7 @@ begin begin info("2.0) test_all_combinations"); - -- Initialize expected output array + -- Initialise expected output array expected_dout_array := new_1d(length => 2**ADDRESS_WIDTH, bit_width => DATA_WIDTH, is_signed => false); for i in ADDR_SEQUENCE'low to ADDR_SEQUENCE'high loop diff --git a/ip/26_Multi_Bit_FIFO/README.md b/ip/26_Multi_Bit_FIFO/README.md new file mode 100644 index 0000000..c8416d0 --- /dev/null +++ b/ip/26_Multi_Bit_FIFO/README.md @@ -0,0 +1,49 @@ +# Quest 26 – Multi-Bit FIFO + +## Original Problem Statement + +### Prompt + +Design a multi-bit First In First Out (FIFO) circuit. The FIFO includes two entries of size `DATA_WIDTH` and requires zero output latency. + +Upon assertion of `resetn` (active-low), the FIFO is reset to zero and the `empty` signal is set to logic high to indicate the FIFO is empty. Once `resetn` is unpressed, the operation starts. The FIFO has a two-entry bank of flip-flops that can be written to by using inputs `din` (data in) and `wr` (write-enable). If `wr` is set to logic low, the input `din` does not get written to the FIFO. + +As the FIFO is being written to, its output port `dout` should imediatelly reflect the first-in data, i.e., there should be no latency between inputs and outputs. Once all entries are written to, the FIFO should output `full = 1` in order to indicate it is full. Writing to a full FIFO is a valid operation and the output `full` must be set to one. + +Important: There are at least three possible states in this design: (1) Empty; (2) Intermediate; (3) Full. Whenever the FIFO is reset, it transitions to state (1). As the entries are updated, the state switches from (1) to (2), and finally from (2) to (3), once completely filled. Use a mux to direct the intermediate stages of the FIFO to the output port `dout` to achieve a low latency design. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Active-low, reset signal +`din` - FIFO input data +`wr` - Active-high, write signal +`dout` - FIFO output data +`full` - Full FIFO indicator +`empty` - Empty FIFO indicator + +### Output signals during reset + +`dout` - 0 +`full` - 0 +`empty` - 1 + +> [!NOTE] +> For the complete problem description, please visit: +> + +## Description + +Two-deep shift-register FIFO. Each write shifts all entries up by one position and inserts new data at index 0. +The `write_count` variable tracks occupancy (0=empty, 1=one entry, 2=full). +Output comes from `memory(write_count - 1)`, always pointing to the oldest entry. +The array range extends to -1 to avoid indexing errors when evaluating expressions in the empty state. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/26). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/27_Dot_Product/README.md b/ip/27_Dot_Product/README.md new file mode 100644 index 0000000..f8fd7ef --- /dev/null +++ b/ip/27_Dot_Product/README.md @@ -0,0 +1,50 @@ +# Quest 27 – Dot Product + +## Original Problem Statement + +### Prompt + +In this question, implement a module that produces the dot product (scalar product) of two equal-length, single dimensional vectors, `A = [a₁, aβ‚‚, a₃]` and `B = [b₁, bβ‚‚, b₃]`. The module has one 8-bit port, `din`, that is used for entering the input sequences of numbers. It also has two outputs, `run`, and `dout`, which return computation status and dot product of the inputs, respectively. + +Assume the sequence is read in the following order: a1, a2, a3, b1, b2, b3. A counter can be used to keep track of the sequence of numbers. Once the 6th number has been registered, output `run` is asserted, and output `dout` returns a scalar 18-b unsigned number corresponding to the dot product of the inputs. In the next cycles, `run` is de-asserted whereas `dout` sustains its previous valid value til the next six numbers of input vectors `A` and `B` are entered. At any rising edge of `clk`, if `resetn` is logic low, then zero is written to the module's internal registers. When `resetn` transitions back from zero to one, `run` is asserted and `dout` is produces zero as `A Β· B = 0`. + +### Input and Output Signals + +`din` - 8-bit unsigned data input word +`clk` - Clock signal +`resetn` - Synchronous, active low, reset signal +`dout` - Output word corresponding to a dot b operation +`run` - Single-bit output signal to indicate a new dot product operation + +### Output signals during reset + +`dout` - 0 +`run` - 1 + +> [!NOTE] +> Quest 27 doesn't exist on chipdev.io. This repository's Quest 27 corresponds to chipdev.io Question 28. +> For the complete problem description, please visit: +> +> +> Note: This is Quest 27 in the repository (chipdev.io is missing Quest #27, so this uses their Quest 28) + +> [!NOTE] +> **Implementation Deviation** +> +> The original problem specifies an 8-bit `din` input, 3-element vectors, and 18-bit `dout` output. This implementation adds `DATA_WIDTH` and `VECTOR_SIZE` generic parameters, making the design configurable for different bit widths and vector sizes. + +## Description + +Sequential dot-product calculator receiving vector elements one at a time. +Accumulates `VECTOR_SIZE * 2` inputs into an array (first `VECTOR_SIZE` elements are vector A, next `VECTOR_SIZE` are vector B), then computes the sum of element-wise products using an impure function. +The `run_out` signal pulses high for one cycle when the calculation completes. +Output width accounts for multiplication growth (`2 * DATA_WIDTH`) plus accumulation growth (`log2(VECTOR_SIZE)`). + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/28). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/28_Binary_to_Thermometer_Decoder/README.md b/ip/28_Binary_to_Thermometer_Decoder/README.md new file mode 100644 index 0000000..a9be1ac --- /dev/null +++ b/ip/28_Binary_to_Thermometer_Decoder/README.md @@ -0,0 +1,41 @@ +# Quest 28 – Binary to Thermometer Decoder + +## Original Problem Statement + +### Prompt + +Thermometer (a.k.a. unary) coding is frequently used in digital systems applications to represent a natural number. In a thermometer code, a `N`-bit binary number is represented by a `(2 ** N)`-bit digital word, which has `m` zeros followed by `(N - m)` ones or vice-versa. + +In this question, implement a binary to thermometer decoder circuit using Verilog. The input, `din`, is an 8-bit unsigned binary word, and the output `dout` is the thermometer code representation of the input at any time. The output is 256-bit long; `dout` has `m` zeros followed by `(256 - m)` ones. + +### Input and Output Signals + +`din` - Binary, unsigned input word +`dout` - Thermometer output word + +> [!NOTE] +> For the complete problem description, please visit: +> +> +> Note: This is Quest 28 in the repository (chipdev.io is missing Quest #27) + +> [!NOTE] +> **Implementation Deviation** +> +> The original problem specifies an 8-bit input and 256-bit output. This implementation adds a `THERMOMETER_WIDTH` generic parameter, making the design configurable for different thermometer code widths. + +## Description + +Binary-to-thermometer code decoder that sets all bits from 0 to the binary input value. +A loop iterates through all output positions, setting each bit if its index is less than or equal to the binary input. +For example, input 5 produces output 0b00111111 (six ones). +The loop-based approach synthesises despite the non-constant range because it evaluates all possibilities at compile time. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/29). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/29_Thermometer_Code_Detector/README.md b/ip/29_Thermometer_Code_Detector/README.md new file mode 100644 index 0000000..9b4acd7 --- /dev/null +++ b/ip/29_Thermometer_Code_Detector/README.md @@ -0,0 +1,35 @@ +# Quest 29 – Thermometer Code Detector + +## Original Problem Statement + +### Prompt + +Thermometer (a.k.a. unary) coding is frequently used in digital systems applications to represent a natural number. In a thermometer code, a `N`-bit binary number is represented by a `(2 ** N)`-bit digital word, which has `m` zeros followed by `(N - m)` ones or vice-versa. + +Implement a thermometer code detector. The module has two ports, `codeIn` and `isThermemeter`. The former is a `DATA_WIDTH`-bit unsigned binary word, and the latter is the signal that indicates whether or not the input is a thermometer code. The circuit must support both types of thermometer representations. For instance, for an input word that is `N`-bit long, the detector must detect thermometer representations that use `m` zeros followed by `(N - m)` ones or `m` ones followed by `(N - m)` zeros. Output `isThermemeter` is one when a thermometer word is detected at the input and zero otherwise. + +### Input and Output Signals + +`codeIn` - Thermometer input word +`isThermometer` - Output bit that indicates whether or not an input word is a thermometer code + +> [!NOTE] +> For the complete problem description, please visit: +> +> +> Note: This is Quest 29 in the repository (chipdev.io is missing Quest #27) + +## Description + +Thermometer code validator ensuring the input contains contiguous ones from LSB. +The function checks that bit 0 is set (LSB must be 1), allows all-ones as valid, then counts bit transitions. +Valid thermometer codes have exactly one transition (from 1 to 0). Early-exit optimisation stops counting after detecting more than one transition. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/30). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/30_Two_Read_One_Write_Register_File/README.md b/ip/30_Two_Read_One_Write_Register_File/README.md new file mode 100644 index 0000000..f6fdfeb --- /dev/null +++ b/ip/30_Two_Read_One_Write_Register_File/README.md @@ -0,0 +1,56 @@ +# Quest 30 – 2-Read 1-Write Register File + +## Original Problem Statement + +### Prompt + +Implement a programmable bitwidth, 32-word 2-read 1-write (2R1W) register file (RF). + +The RF has 32 entries, each of which being a `DATA_WIDTH`-bit binary word. The input word `din` is written to one of the entries of the RF by using the write address port `wad1` and asserting signal `wen1`. Entries are read from the RF by selecting the addresses and asserting the `ren1` and/or `ren2` signals. The RF must support up to three operations per clock cycle, that is, two reads and one write; no operations (NOP), one, and two operations must be also supported. + +The default value of both `dout1` and `dout2` is zero. If, at the rising edge of the clock, one of the read-enable ports is deasserted, then it is expected that its respective data-output port produces the default value (zero). If one tries to read from an address that has never been written to, then `dout1` and/or `dout2` produce zero. + +RF's output port `collision = 1` when at least two out of three input addresses are equal, and `collision = 0` otherwise. That is, the RF must flag when one tries to write to and read from the same address (`wad1 = rad1 or wad1 = rad2`), or attempts to read from the same address using both read ports (`rad1 or wad1 = rad2`). + +### Input and Output Signals + +`din` - Input data port +`wad1` - Write input address 1 +`rad1` - Read input address 1 +`rad2` - Read input address 2 +`wen1` - Write-enable signal 1 +`ren1` - Read-enable input signal 1 +`ren2` - Read-enable input signal 2 +`clk` - Clock signal +`resetn` - Synchronous, active-low, reset signal +`dout1` - Output data port 1 +`dout2` - Output data port 2 +`collision` - Indicates collisions among read & write addresses + +### Output signals during reset + +`dout1` - 0 +`dout2` - 0 +`collision` - 0 + +> [!NOTE] +> For the complete problem description, please visit: +> +> +> Note: This is Quest 30 in the repository (chipdev.io is missing Quest #27) + +## Description + +Dual-port read, single-port write register file with collision detection. +Maintains `2^ADDRESS_WIDTH` registers implemented as a signal array. +Collisions occur when: (1) both read ports target the same address, (2) write and read1 target the same address, or (3) write and read2 target the same address - all while their respective enables are active. +When collision is detected, all operations are blocked and outputs zero. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/31). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/31_Configurable_LFSR/README.md b/ip/31_Configurable_LFSR/README.md new file mode 100644 index 0000000..ab8f811 --- /dev/null +++ b/ip/31_Configurable_LFSR/README.md @@ -0,0 +1,43 @@ +# Quest 31 – Configurable LFSR + +## Original Problem Statement + +### Prompt + +A Linear-Feedback Shift Register (LFSR) is a type a of shift-register that can generate a pseudo-random stream of binary words. The shift-register is configured in a ring fashion. A feedback loop is created by XOR-ing the ouputs of specific stages (also known as taps) of the shift-register and connecting them to the input of its first stage. + +In this question, implement a LFSR that can produce a pseudorandom sequence of `DATA_WIDTH`-bit output words. The inputs to the module are `din`, which is the initial value written to the shift-register upon reset, `tap`, which is a `DATA_WIDTH`-bit word corresponding to the feedback polynomial to the LFSR, and `resetn`, which resets the shift-register. In a Fibonacci LFSR with 16 stages, `tap = 16'b1011_0100_0000_0000` because the XOR inputs are coming from outputs of stages 16, 14, 13, and 11. That is, the position of the one bits in tap determines the inputs to the XOR tree. Assume the input tap is buffered/registered inside the module. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous, active low, reset signal +`din` - Input data (initial data input value, e.g. 8'b0000_0001) +`tap` - Input tap (feedback polynomial, e.g. 8'b1011_0101) +`dout` - Output data + +### Output signals during reset + +`dout` - 1 + +> [!NOTE] +> For the complete problem description, please visit: +> +> +> Note: This is Quest 31 in the repository (chipdev.io is missing Quest #27) + +## Description + +Configurable Linear Feedback Shift Register with runtime-programmable tap positions. +The `tap` input specifies which bit positions contribute to the feedback calculation. +Each clock cycle computes the feedback bit as the XOR reduction of all tapped positions (`xor(tap_reg and shift_reg)`), then shifts this feedback into the LSB. +The tap configuration and seed value are captured during reset. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/32). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/32_Carry_Select_Adder/README.md b/ip/32_Carry_Select_Adder/README.md new file mode 100644 index 0000000..eeffaa2 --- /dev/null +++ b/ip/32_Carry_Select_Adder/README.md @@ -0,0 +1,38 @@ +# Quest 32 – Carry-Select Adder + +## Original Problem Statement + +### Prompt + +Use the solutions to questions 22 & 24 (Full Adder and Ripper Carry Adder, respectively) to implement a 24-bit Carry Select Adder (CSA). CSAs commonly employ two Ripple Carry Adders (RCAs) which compute `a + b + cin`, where `cin = 0` in one computation, and `cin = 1` in the other. The final result is obtained by selecting the correct partial sum, based on the `cout` bit of the previous stage. + +In this question, implement a 24-bit Carry Select Adder (CSA) using multiple parallel RCAs and multiplexers. The CSA module takes two unsigned integers `a` and `b`, and produces an output word `sum`, corresponding to `a + b` operation. The number of RCA stages in the CSA can be chosen by the designer, e.g., 3 stages of 8-bit RCAs, 4 stages of 6-bit RCAs, etc. Bonus: Can you design a parametric number of stage 24-bit CSA? Test your design with various number of RCA stages. + +### Input and Output Signals + +`a` - First operand input word +`b` - Second operand input word +`result` - Output word corresponding to a plus b operation (25-bit word since both a and b are 24-bit) + +> [!NOTE] +> For the complete problem description, please visit: +> +> +> Note: This is Quest 32 in the repository (chipdev.io is missing Quest #27) + +## Description + +Carry-select adder dividing the operands into `STAGES` blocks plus an optional remainder stage. +Each stage instantiates two ripple-carry adders computing results for both carry-in possibilities (0 and 1). +A multiplexer chain selects the correct sum based on the actual carry from the previous stage. +When `DATA_WIDTH` doesn't divide evenly by `STAGES`, remaining bits form an additional stage. +This architecture trades area for reduced carry propagation delay compared to pure ripple-carry. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/33). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/33_Bubble_Sort/README.md b/ip/33_Bubble_Sort/README.md new file mode 100644 index 0000000..b68f4b7 --- /dev/null +++ b/ip/33_Bubble_Sort/README.md @@ -0,0 +1,44 @@ +# Quest 33 – Bubble Sort + +## Original Problem Statement + +### Prompt + +Design a module that implements the bubble sort algorithm within one cycle. The module takes three inputs: `din`, which corresponds to a `BITWIDTH`-bit unsigned word; `sortit`, a 1-bit signal that is asserted in order to start a new sort operation; and `resetn`, a synchronous, active-low reset signal. The module's output is a `(8*BITWIDTH+1)`-bit unsigned bitstream that corresponds to a sorted vector of `(8*BITWIDTH)` unsigned words, which were stored in the module's memory when the input `sortit` is asserted. + +Input `sortit` is an asynchronous signal, coming from another module. Assume there's no need to flop it. Inputs are registered only when `sortit = 0` and ignored otherwise. Output `dout` is valid only when `sortit = 1`. That is, the sorted vector is produced only when `sortit = 1`, or else `dout` is expected to produce zero. The output vector is sorted in a descending order. The `BITWIDTH` most significant bits correpond to the smallest value whereas the `BITWIDTH` least significant bits correspond to the largest value. + +### Input and Output Signals + +`din` - Unsigned data input word +`sortit` - Sort input bit +`clk` - Clock signal +`resetn` - Synchronous, active low, reset signal +`dout` - Output word corresponding to the sorted, concantenated memory-stored values when sortit is asserted + +### Output signals during reset + +`dout` - 0 + +> [!NOTE] +> For the complete problem description, please visit: +> +> +> Note: This is Quest 33 in the repository (chipdev.io is missing Quest #27) + +## Description + +Hardware bubble sort collecting VECTOR_SIZE elements then sorting when `sortit` asserts. +During collection phase, incoming data fills a memory array via a wrapping counter. +When triggered, the `bubble_sorter` function performs nested-loop comparisons, swapping adjacent elements when out of order. +The sorted result is reformatted with the largest value in the MSBs via `get_sorted_vector`. +`O(n^2)` time complexity executed combinationally within one clock cycle. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/34). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:** diff --git a/ip/34_Mealy_Finite_State_Machine/README.md b/ip/34_Mealy_Finite_State_Machine/README.md new file mode 100644 index 0000000..908c959 --- /dev/null +++ b/ip/34_Mealy_Finite_State_Machine/README.md @@ -0,0 +1,48 @@ +# Quest 34 – Mealy Finite State Machine + +## Original Problem Statement + +### Prompt + +In this question, design a Mealy Finite State Machine (FSM) that has five states, `S0`-`S4`. Upon `resetn` logic low, the FSM resets and current state becomes `S0`. The inputs `din` and `cen` are registered inside the module, therefore, their registers also reset to zero. + +When `resetn = 1`, the FSM starts its operation. `doutx` must produce one whenever the current cycle `din` as well as the previous cycle `din` have the same values. Similarly, `douty` must output one whenever the current cycle `din` is the same now as it was for the past two cycles. Input `cen` (the registered version of it, inside the module) is used to gate the output. That is, in a particular cycle, if `cen = 0`, then outputs `doutx` and `douty` are both zero. + +Try to solve this question using a textbook Mealy FSM approach. Sketch the state diagrams with the five possible state and the allowed transitions between them. + +### Input and Output Signals + +`clk` - Clock signal +`resetn` - Synchronous, active low, reset signal +`cen` - Chip enable +`din` - 1-bit input a +`doutx` - 1-bit output x +`douty` - 1-bit output y + +### Output signals during reset + +`doutx` - 0 +`douty` - 0 + +> [!NOTE] +> For the complete problem description, please visit: +> +> +> Note: This is Quest 34 in the repository (chipdev.io is missing Quest #27) + +## Description + +Mealy finite state machine with outputs depending on both current state and inputs. +Five states track input history: S0 (initial), S1/S2 (saw zeros), S3/S4 (saw ones). +The `din_reg` and `cen_reg` signals capture inputs synchronously to avoid combinational timing issues. +Output `doutx` pulses when receiving consecutive matching bits (00 or 11), while `douty` requires at least two previous matching bits. +Both outputs gate through `cen_reg` for external enable control. + +## Source + +This quest is from [chipdev.io](https://chipdev.io/question/35). + +The problem description above is used under fair use for educational purposes. +For licensing information, see [LICENSE-THIRD-PARTY.md](../../LICENSE-THIRD-PARTY.md). + +**Webarchive link:**