/ Hardware Design

Brainfuck CPU in Verilog

I wanted to start learning Verilog and made a really simple brainfuck CPU.

Specifications:

Memory16384 Bytes
Cell size1 Byte
Cell overflowWrap
Address overflowWrap
Max code size1024 Instructions
Maximum nested loops512
I/OFull stdin/stdout
Can be synthesizedNope
Registers139314 Bits
module main;
    reg [7:0] mem [0:16383];
    reg [13:0] ptr = 0;
    reg [2:0] code [0:1023];
    reg [9:0] pc = 0;
    reg [9:0] stack [0:511];
    reg [9:0] sp = 0;
    integer stdin, stdout;
    reg clk = 0;

    reg [7:0] skip = 0;
    integer tmp1;
    reg [7:0] tmp2;

    always @(posedge clk) begin
        if (skip) begin
            if (code[pc] == 3'b110) skip++; // [
            if (code[pc] == 3'b111) skip--; // ]
        end else case(code[pc])
            3'b000: mem[ptr]++; // +
            3'b001: mem[ptr]--; // -
            3'b010: $fwrite(stdout, "%c", mem[ptr]); // .
            3'b011: begin
                tmp1 = $fread(tmp2, stdin); // ,
                mem[ptr] = tmp2;
            end
            3'b100: ptr++; // >
            3'b101: ptr--; // <
            3'b110: begin // [
                if (!mem[ptr]) begin
                    skip = 1;
                end else begin
                    stack[sp] = pc;
                    sp++;
                end
            end
            3'b111: begin // ]
                if (mem[ptr]) begin
                    pc = stack[sp - 1];
                end else begin
                    sp--;
                end
            end
        endcase
        pc++;
        if (pc == 0) $finish;
    end

    integer k;
    initial begin
        for (k = 0; k < 16383; k = k + 1) mem[k] = 0;
        for (k = 0; k < 1023; k = k + 1) code[k] = 0;
        for (k = 0; k < 255; k = k + 1) stack[k] = 0;
        code[0] = 3'b000;
        code[1] = 3'b110;
        code[2] = 3'b011;
        code[3] = 3'b010;
        code[4] = 3'b111;
        stdin = $fopen("/dev/stdin", "r");
        stdout = $fopen("/dev/stdout", "w");
    end

    always #1 clk = ~clk;
endmodule

I have pre-loaded the cat program +[,.] which echos back everything you input.

To compile it i am using Icarus Verilog:

pixel@pixel-PC:~/bfcpu$ iverilog -o bf bf.v  
pixel@pixel-PC:~/bfcpu$ ./bf  
Hello  
Hello  
World  
World  

And it works!

Unfortunately it cannot be synthesized because it uses file I/O and because I am using arrays instead of memory.

Brainfuck CPU in Verilog
Share this