Add diagrams and pictures
[clump.git] / worker.v
1 `include "pll.v"
2 `include "ram.v"
3 `include "chip.v"
4 `include "uart.v"
5
6 `ifdef SIM
7 `define UART_DIVIDE 1
8 `else
9 `define UART_DIVIDE 1024
10 `endif
11
12 module worker (input CLKin, output [4:0] led, output uart_tx, input uart_rx, output reg busy_out = 1, input busy_in, input is_worker);
13 wire clk = CLKin;
14
15 `ifndef SIM
16 // if [is_worker == 0], boot into master image
17 SB_WARMBOOT wb (.BOOT (!is_worker), .S0(1'b1), .S1(1'b0));
18 `endif
19
20 `ifdef SIM
21 wire dont_send = 0;
22 `else
23 reg [25:0] dont_send = 23'b11111111111111111111111;
24
25 always @(posedge clk) begin
26 if(busy_in)
27 dont_send <= 21'b111111111111111111111;
28 else if(dont_send)
29 dont_send <= dont_send - 1;
30 end
31 `endif
32
33 wire [11:0] mem_addr;
34 wire [15:0] mem_in;
35 wire [15:0] mem_out;
36 wire mem_write;
37
38 reg [31:0] the_rom [0:100];
39 reg [10:0] rom_pc = 0;
40
41 initial begin
42 the_rom[0] <= 32'hfC000005;
43 the_rom[1] <= 32'hfC010007;
44 the_rom[2] <= 32'hf9001d00;
45 the_rom[3] <= 32'hfA0112d0;
46 the_rom[4] <= 32'hfB000004;
47 the_rom[5] <= 32'hf9000004;
48 the_rom[6] <= 32'hfA001550;
49 the_rom[7] <= 32'hfB010000;
50 end
51
52 RAM #(.ADDRESS_BITS(8)) ram (.clk(clk), .write(mem_write), .addr(mem_addr), .in(mem_in), .out(mem_out));
53
54 reg [7:0] from_uart [3:0];
55 reg [2:0] uart_ptr = 0;
56
57 wire [15:0] I = {from_uart[1], from_uart[0]};
58 assign mem_addr = from_uart[2];
59 wire [2:0] op_from_uart = from_uart[3][2:0];
60
61 wire [3:0] chip_select = from_uart[3][7:4];
62 wire is_virtual = from_uart[3][3];
63 wire dont_propagate = is_virtual || ~| chip_select;
64 wire not_for_us = !chip_select[0];
65
66 wire [7:0] to_uart [3:0];
67 wire [3:0] next_chip_select = {0, chip_select[3:1]};
68 assign to_uart[0] = from_uart[0];
69 assign to_uart[1] = from_uart[1];
70 assign to_uart[2] = from_uart[2];
71 assign to_uart[3] = {next_chip_select, from_uart[3][3:0]};
72
73 /* to execute a ROUTE instruction, we send our neighbour a STOREI
74 /* instruction with the correct address and value. This is the
75 /* STOREI instruction. */
76 wire [7:0] route_storei [3:0];
77 assign route_storei[0] = mem_out[7:0];
78 assign route_storei[1] = mem_out[15:8];
79 assign route_storei[2] = from_uart[0];
80 assign route_storei[3] = 8'h1C; // chip_select = 1, is_virtual = 1, op = OP_STOREI
81
82 reg [2:0] op = 0;
83
84 reg [2:0] last_op = 0;
85
86 reg [15:0] I;
87
88 reg [3:0] led_out;
89
90 chip chip (.clk(clk), .op(op), .I(I), .mem_in(mem_in), .mem_out(mem_out), .mem_write(mem_write), .led_out(led_out));
91
92 wire received;
93 wire [7:0] rx_byte;
94 reg transmit = 0;
95 reg [7:0] tx_byte = 0;
96 wire is_receiving;
97 wire is_transmitting;
98 wire recv_error;
99
100 uart #(.CLOCK_DIVIDE(`UART_DIVIDE)) uart (.clk(clk), .rx(uart_rx), .tx(uart_tx), .received(received), .transmit(transmit), .tx_byte(tx_byte), .rx_byte(rx_byte), .is_receiving(is_receiving), .is_transmitting(is_transmitting), .recv_error(recv_error));
101
102 `define STATE_IDLE 0
103 `define STATE_PROPAGATE 1
104 `define STATE_PREEXEC 2
105 `define STATE_EXECUTE 3
106 `define STATE_ROUTE 4
107
108 reg [3:0] state = `STATE_IDLE;
109
110 assign led[3:0] = uart_ptr;
111 assign led[4] = is_receiving;
112
113 always @ (posedge clk) begin
114 case(state)
115 `STATE_IDLE: begin
116 if(uart_ptr == 4) begin
117 last_op <= op_from_uart;
118 uart_ptr <= 0;
119 if(dont_propagate)
120 state <= `STATE_PREEXEC;
121 else
122 state <= `STATE_PROPAGATE;
123 busy_out <= 1;
124 end
125 else if (received) begin
126 from_uart[uart_ptr] <= rx_byte;
127 uart_ptr <= uart_ptr + 1;
128 end else begin
129 `ifdef SIM
130 from_uart[0] <= the_rom[rom_pc][7:0];
131 from_uart[1] <= the_rom[rom_pc][15:8];
132 from_uart[2] <= the_rom[rom_pc][23:16];
133 from_uart[3] <= the_rom[rom_pc][31:24];
134 uart_ptr <= 4;
135 rom_pc <= rom_pc + 1;
136 `else
137 busy_out <= 0;
138 `endif
139 end
140 end
141
142 `STATE_PROPAGATE: begin
143 if(transmit)
144 transmit <= 0;
145 else if(uart_ptr == 4) begin
146 uart_ptr <= 0;
147 state <= `STATE_PREEXEC;
148 end else if(!is_transmitting && !dont_send) begin
149 tx_byte <= to_uart[uart_ptr];
150 transmit <= 1;
151 uart_ptr <= uart_ptr + 1;
152 end
153 end // case: `STATE_PROPAGATE
154
155 `STATE_PREEXEC: begin
156 if(not_for_us) begin
157 state <= `STATE_IDLE;
158 end else if(last_op == `OP_ROUTE) begin
159 state <= `STATE_ROUTE;
160 end else begin
161 op <= last_op;
162 state <= `STATE_EXECUTE;
163 end
164 end
165
166 `STATE_EXECUTE: begin
167 op <= 0;
168 state <= `STATE_IDLE;
169 end
170
171 `STATE_ROUTE: begin
172 if(transmit)
173 transmit <= 0;
174 else if(uart_ptr == 4) begin
175 uart_ptr <= 0;
176 state <= `STATE_IDLE;
177 end else if(!is_transmitting && !dont_send) begin
178 tx_byte <= route_storei[uart_ptr];
179 transmit <= 1;
180 uart_ptr <= uart_ptr + 1;
181 end
182 end
183 endcase
184 end
185 endmodule
This page took 0.026818 seconds and 4 git commands to generate.