diff options
-rw-r--r-- | collatz.v | 57 | ||||
-rw-r--r-- | collatz_tb.v | 48 |
2 files changed, 105 insertions, 0 deletions
diff --git a/collatz.v b/collatz.v new file mode 100644 index 0000000..e90c1bd --- /dev/null +++ b/collatz.v @@ -0,0 +1,57 @@ +module collatz ( + input clk, + input rst, + + input wire [15:0] in_start, + input wire start_int, + + output reg [15:0] o_count, + output finish_int +); + + localparam IDLE = 0; + localparam SPINNING = 1; + localparam WAIT_TICK = 2; + + reg [1:0] state = 0; + reg [15:0] count = 0; + reg [15:0] n = 0; + + wire is_even; + + assign is_even = ~n[0]; + assign finish_int = (n == 1 && state == IDLE); + + always @(posedge start_int) begin + if (state == IDLE) begin + state <= SPINNING; + n <= in_start; + end + end + + always @(posedge clk or posedge rst) begin + if (rst == 1'b1) begin + state <= IDLE; + count <= 0; + n <= 0; + end else if (state == IDLE) begin + n <= 0; + end else if (state == SPINNING) begin + if (n <= 1) begin + o_count = count; + state = WAIT_TICK; + // finish_int should be triggered. + end else begin + if (is_even) begin + n <= n >> 1; + end else begin + n <= n * 3 + 1; + end + count <= count + 1; + end + end else if (state == WAIT_TICK) begin + state <= IDLE; + end + end + + endmodule diff --git a/collatz_tb.v b/collatz_tb.v new file mode 100644 index 0000000..7419d3f --- /dev/null +++ b/collatz_tb.v @@ -0,0 +1,48 @@ +`timescale 1 ns / 10 ps + +module collatz_tb (); + reg clk = 0; + reg rst = 0; + + wire finish; + + localparam integer DURATION = 10_000; + + always begin + #41.667; + + clk = ~ clk; + end + + reg [15:0] n = 9; + reg start_int; + + wire [15:0] count_out; + + collatz ctz ( + .clk(clk), + .rst(rst), + .in_start(n), + .start_int(start_int), + .o_count(count_out), + .finish_int(finish) + ); + + initial begin + #10 rst = 1'b1; + #1 rst = 1'b0; + end + + initial begin + $dumpfile("collatz_tb.vcd"); + $dumpvars(0, collatz_tb); + + #50 start_int = 1; + #10 start_int = 0; + + #(DURATION); + $display("Finished!"); + $finish; + end + +endmodule |