summaryrefslogtreecommitdiff
path: root/hdl/top.sv
blob: aa5a4e2c1818e58ea3caf22e244b645037ab3038 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
`include "util.svh"

module top
    #(  ADDR_BITS   = 14
    ,   DATA_BITS   = 12
    )
    (   input   bit clk     // verilator public
    ,   input   bit reset_n // verilator public
    );

bit reset = 0;
bit have_reset = 0;
always_ff @(posedge clk) if (reset) have_reset <= 1;
assign reset = !reset_n || !have_reset;

bit [DATA_BITS-1:0] mem [0:(1<<ADDR_BITS)-1];
initial $readmemh("mem/mem.hex", mem);

bit rx_ready;
bit rx_valid;
bit [7:0] rx_data;

bit tx_ready;
bit tx_valid;
bit [7:0] tx_data;

jtag_uart
    #(  .INSTANCE(0)
    ) uart0
    (   .clk(clk)
    ,   .reset(reset)

    ,   .rx_ready(rx_ready)
    ,   .rx_valid(rx_valid) `define rx_valid `past(rx_valid)
    ,   .rx_data(rx_data)   `define rx_data `past(rx_data)

    ,   .tx_ready(tx_ready) `define tx_ready `past(tx_ready)
    ,   .tx_valid(tx_valid)
    ,   .tx_data(tx_data)
    );

bit [DATA_BITS-1:0] pc;
bit [3:0] opcode;
bit [7:0] operand;
bit [DATA_BITS-1:0] acc;
bit [DATA_BITS-1:0] idx;

enum
    {   FETCH
    ,   DECODE
    } state;

always_ff @(posedge clk) begin
    if (reset) begin
        rx_ready = 0;
        tx_valid = 0;
        tx_data = 0;
        pc = 0;
        acc = 0;
        idx = 0;
        state = state.first;
    end else begin
        if (`tx_ready) tx_valid = 0;

        case (state)
            FETCH: begin
                {opcode, operand} = mem[{2'b0, pc}];
                ++pc;
                state = DECODE;
            end

            DECODE: begin
                //$display("%x %x:%x (acc=%x idx=%x)", pc, opcode, operand, acc, idx);
                state = FETCH;
                case (opcode)
                    'h0: acc = {{4{operand[7]}}, operand};
                    'h1: acc = mem[idx + operand];
                    'h2: mem[idx + operand] = acc;
                    'h3: if (acc != operand) ++pc;
                    'h4: pc = pc + {{4{operand[7]}}, operand};
                    'hf: begin
                        if (operand[0]) ++acc;
                        if (operand[1]) --acc;
                        if (operand[2]) ++idx;
                        if (operand[3]) --idx;
                        if (operand[4]) {idx, acc} = {acc, idx};
                        if (operand[5]) idx = acc;
                        if (operand[6]) begin
                            if (tx_valid) begin
                                state = DECODE;
                            end else begin
                                tx_valid = 1;
                                tx_data = acc[7:0];
                            end
                        end
                        if (operand[7]) state = DECODE;
                    end
                endcase
            end
        endcase
    end
end

endmodule