chipdev

chipdev.io Solutions (0x6A73)
git clone https://git.pngu.org/chipdev
Log | Files | Refs | README

commit 80ab141c6154b79ce45b0cc433405c39b58408be
parent 5b971562baea51a4683195d482f0141717f93738
Author: Jack Sangdahl <jack@pngu.org>
Date:   Wed, 19 Nov 2025 11:55:08 -0700

Q1. Simple Router

Diffstat:
Aq1_router/Makefile | 8++++++++
Aq1_router/readme.md | 32++++++++++++++++++++++++++++++++
Aq1_router/router.v | 18++++++++++++++++++
Aq1_router/router_test.py | 33+++++++++++++++++++++++++++++++++
4 files changed, 91 insertions(+), 0 deletions(-)

diff --git a/q1_router/Makefile b/q1_router/Makefile @@ -0,0 +1,8 @@ +SIM = verilator +TOPLEVEL_LANG = verilog +VERILOG_SOURCES = $(PWD)/router.v +COCOTB_TOPLEVEL = model +COCOTB_TEST_MODULES = router_test +WAVES = 1 + +include $(shell cocotb-config --makefiles)/Makefile.sim diff --git a/q1_router/readme.md b/q1_router/readme.md @@ -0,0 +1,32 @@ +# Simple Router + +## Prompt +Build a router circuit which forwards data from the input (`din`) to one of four outputs (`dout0`, `dout1`, `dout2`, `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 `dout{address decimal value}`. 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 & Output Signals +- `din`: Input data. +- `din_en`: Enable signal for `din`. Forwards data from input to an output if 1, does not forward 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`. + +## Example: +- Data width: 32 +- Input 1 + - `din = hbee` + - `din_en`: True + - `addr = h1` +- Input 2 + - `din = hbee` + - `din_en`: True + - `addr = h3` +- Input 3 + - `din = hbee` + - `din_en`: False + - `addr = h3` diff --git a/q1_router/router.v b/q1_router/router.v @@ -0,0 +1,18 @@ +module model #( + parameter DATA_WIDTH = 32 +) ( + input [DATA_WIDTH-1:0] din, + input din_en, + input [1:0] addr, + output logic [DATA_WIDTH-1:0] dout0, + output logic [DATA_WIDTH-1:0] dout1, + output logic [DATA_WIDTH-1:0] dout2, + output logic [DATA_WIDTH-1:0] dout3 +); + + assign dout0 = (din_en && addr == 0) ? din : 0; + assign dout1 = (din_en && addr == 1) ? din : 0; + assign dout2 = (din_en && addr == 2) ? din : 0; + assign dout3 = (din_en && addr == 3) ? din : 0; + +endmodule diff --git a/q1_router/router_test.py b/q1_router/router_test.py @@ -0,0 +1,33 @@ +import cocotb +from cocotb.triggers import Timer + + +@cocotb.test() +async def test_router(dut): + def check_outputs(expected_values, step_desc): + dut._log.info(step_desc) + for i in range(4): + expected = expected_values[i] + actual = getattr(dut, f"dout{i}").value.to_unsigned() + assert actual == expected, ( + f"dout{i}: got 0x{actual:x}, expected 0x{expected:x}" + ) + + dut.addr.value = 0x1 + dut.din_en.value = 1 + dut.din.value = 0xBEE + dout1 = [0x0, 0xBEE, 0x0, 0x0] + await Timer(1, unit="ns") + check_outputs(dout1, "state 1: addr = 1, din_en = 1, din = 0xBEE, dout1 = 0xBEE") + + dut.addr.value = 0x3 + dout2 = [0x0, 0x0, 0x0, 0xBEE] + await Timer(1, unit="ns") + check_outputs(dout2, "state 2: addr = 3, din_en = 1, din = 0xBEE, dout3 = 0xBEE") + + dut.din_en.value = 0 + dout3 = [0x0, 0x0, 0x0, 0x0] + await Timer(1, unit="ns") + check_outputs( + dout3, "state 3: addr = 3, din_en = 0, din = 0xBEE, dout{0,1,2,3} = 0" + )