solved by hartmannsyg
I want to count from 0
Author: Hackin7nc challs.nusgreyhats.org 31114
we are given run.py
, which takes our input verilog code and runs it with iverilog:
iverilog -o ./vt -s test -c file_list.txt vvp ./vt > output.txt |
run.py
source code
1 | #!/usr/bin/python3 |
Apparently, our output should follow expected_output.txt
:
1 | clk 0, result 0 clk 1, result 1 clk 0, result 1 clk 1, result 2 clk 0, result 2 clk 1, result 3 clk 0, result 3 clk 1, result 4 clk 0, result 4 clk 1, result 5 |
Wtf is iverilog
This seems a bit like an “esolang” (esoteric language) challenges that ctfs will randomly have so oh well
Let’s first checking Wikipedia (The Free Encyclopedia)
Icarus Verilog is an implementation of the Verilog hardware description language compiler that generates netlists in the desired format (EDIF) and a simulator.
uhhh idk what those are but alright then. I think my favoruite part of this (very short) Wikipedia page is this sentence:
Not even the author quite remembers when the project was first started, but CVS records go back to 1998.
yikes
Installing
Somehow this was quite troublesome. When I downloaded the challenge, I completely forgot that there was a docker-compose.yml
given. So I googled online and went to their Fandom Website (a fandom wiki for documentation …)
I tried installing it on my WSL kali linux but I failed spectacularly, so I tried it on Windows instead. After a bunch of fumbling around I got their hello world example running:
1 | module hello; initial begin $display("Hello, World"); $finish ; end endmodule |
The objective
After the daunting task of getting iverilog, let’s get to the point of this challenge.
The python script saved our input to solve.v
, and then compiles both solve.v
and testbench.v
with:
iverilog -o ./vt -s test -c file_list.txt |
file_list.txt
in this case is a file that contains the list of files to be compiled:
1
2 solve.v
testbench.v
Let’s look at testbench.v
:
1 | module test(); // Inputs reg clk; // Outputs wire [31:0] result; counter c(clk, result); initial begin clk = 0; $monitor("clk %b, result %d", clk, result); repeat(131076) begin #1 clk = ~clk; end end endmodule |
We see that if we simply try to run it, we encounter an error:
C:\iverilog\bin>iverilog testbench.v testbench.v:7: error: Unknown module type: counter 2 error(s) during elaboration. *** These modules were missing: counter referenced 1 times. *** |
Debugging
as we thought, we need to make a counter
module. Thankfully, we see that in the iverilog fandom documentation there is an implementation of the counter
module:
1 | module counter(out, clk, reset); |
Running both testbench.v
and counter.v
gives us:
C:\iverilog\bin>iverilog testbench.v counter.v testbench.v:7: error: Wrong number of ports. Expecting 3, got 2. 1 error(s) during elaboration. |
we see that counter should have clk
as its first parameter (are they called parameters? idk the terminology here) and result
(which corresponds to out
in the example code) as the second parameter, with no reset
parameter:
1 | module test(); // Inputs reg clk; // Outputs wire [31:0] result; |
So let’s rewrite our counter module:
module counter(clk, out); parameter WIDTH = 8; output [WIDTH-1: 0] out; input clk; reg [WIDTH-1: 0] out; wire clk; always @(posedge clk) out <= out + 1; endmodule // counter |
Let’s see what we error we get:
C:\iverilog\bin>iverilog testbench.v counter.v testbench.v:7: warning: Port 2 (out) of counter expects 8 bits, got 32. testbench.v:7: : Padding 24 high bits of the expression. |
Alright let’s make out
be 32 bits
1 | parameter WIDTH = 32; |
aaaand we get an infinite loop…
clk 0, result x clk 1, result x |
???? Why isn’t out outputting the result????
I then asked chatGPT and they suggested more code I had to debug. I won’t get into the nitty-gritty debugging process but here are some takeaways:
I eventually arrived at:
1 | module counter(input clk, output reg [31:0] result); initial begin result <= 0; end always @(posedge clk) begin result <= result - -1; end endmodule |