`include "pll.v" `include "ram.v" `include "chip.v" `include "uart.v" `ifdef SIM `define UART_DIVIDE 1 `else `define UART_DIVIDE 1024 `endif 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); wire clk = CLKin; `ifndef SIM // if [is_worker == 0], boot into master image SB_WARMBOOT wb (.BOOT (!is_worker), .S0(1'b1), .S1(1'b0)); `endif `ifdef SIM wire dont_send = 0; `else reg [25:0] dont_send = 23'b11111111111111111111111; always @(posedge clk) begin if(busy_in) dont_send <= 21'b111111111111111111111; else if(dont_send) dont_send <= dont_send - 1; end `endif wire [11:0] mem_addr; wire [15:0] mem_in; wire [15:0] mem_out; wire mem_write; reg [31:0] the_rom [0:100]; reg [10:0] rom_pc = 0; initial begin the_rom[0] <= 32'hfC000005; the_rom[1] <= 32'hfC010007; the_rom[2] <= 32'hf9001d00; the_rom[3] <= 32'hfA0112d0; the_rom[4] <= 32'hfB000004; the_rom[5] <= 32'hf9000004; the_rom[6] <= 32'hfA001550; the_rom[7] <= 32'hfB010000; end RAM #(.ADDRESS_BITS(8)) ram (.clk(clk), .write(mem_write), .addr(mem_addr), .in(mem_in), .out(mem_out)); reg [7:0] from_uart [3:0]; reg [2:0] uart_ptr = 0; wire [15:0] I = {from_uart[1], from_uart[0]}; assign mem_addr = from_uart[2]; wire [2:0] op_from_uart = from_uart[3][2:0]; wire [3:0] chip_select = from_uart[3][7:4]; wire is_virtual = from_uart[3][3]; wire dont_propagate = is_virtual || ~| chip_select; wire not_for_us = !chip_select[0]; wire [7:0] to_uart [3:0]; wire [3:0] next_chip_select = {0, chip_select[3:1]}; assign to_uart[0] = from_uart[0]; assign to_uart[1] = from_uart[1]; assign to_uart[2] = from_uart[2]; assign to_uart[3] = {next_chip_select, from_uart[3][3:0]}; /* to execute a ROUTE instruction, we send our neighbour a STOREI /* instruction with the correct address and value. This is the /* STOREI instruction. */ wire [7:0] route_storei [3:0]; assign route_storei[0] = mem_out[7:0]; assign route_storei[1] = mem_out[15:8]; assign route_storei[2] = from_uart[0]; assign route_storei[3] = 8'h1C; // chip_select = 1, is_virtual = 1, op = OP_STOREI reg [2:0] op = 0; reg [2:0] last_op = 0; reg [15:0] I; reg [3:0] led_out; chip chip (.clk(clk), .op(op), .I(I), .mem_in(mem_in), .mem_out(mem_out), .mem_write(mem_write), .led_out(led_out)); wire received; wire [7:0] rx_byte; reg transmit = 0; reg [7:0] tx_byte = 0; wire is_receiving; wire is_transmitting; wire recv_error; 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)); `define STATE_IDLE 0 `define STATE_PROPAGATE 1 `define STATE_PREEXEC 2 `define STATE_EXECUTE 3 `define STATE_ROUTE 4 reg [3:0] state = `STATE_IDLE; assign led[3:0] = uart_ptr; assign led[4] = is_receiving; always @ (posedge clk) begin case(state) `STATE_IDLE: begin if(uart_ptr == 4) begin last_op <= op_from_uart; uart_ptr <= 0; if(dont_propagate) state <= `STATE_PREEXEC; else state <= `STATE_PROPAGATE; busy_out <= 1; end else if (received) begin from_uart[uart_ptr] <= rx_byte; uart_ptr <= uart_ptr + 1; end else begin `ifdef SIM from_uart[0] <= the_rom[rom_pc][7:0]; from_uart[1] <= the_rom[rom_pc][15:8]; from_uart[2] <= the_rom[rom_pc][23:16]; from_uart[3] <= the_rom[rom_pc][31:24]; uart_ptr <= 4; rom_pc <= rom_pc + 1; `else busy_out <= 0; `endif end end `STATE_PROPAGATE: begin if(transmit) transmit <= 0; else if(uart_ptr == 4) begin uart_ptr <= 0; state <= `STATE_PREEXEC; end else if(!is_transmitting && !dont_send) begin tx_byte <= to_uart[uart_ptr]; transmit <= 1; uart_ptr <= uart_ptr + 1; end end // case: `STATE_PROPAGATE `STATE_PREEXEC: begin if(not_for_us) begin state <= `STATE_IDLE; end else if(last_op == `OP_ROUTE) begin state <= `STATE_ROUTE; end else begin op <= last_op; state <= `STATE_EXECUTE; end end `STATE_EXECUTE: begin op <= 0; state <= `STATE_IDLE; end `STATE_ROUTE: begin if(transmit) transmit <= 0; else if(uart_ptr == 4) begin uart_ptr <= 0; state <= `STATE_IDLE; end else if(!is_transmitting && !dont_send) begin tx_byte <= route_storei[uart_ptr]; transmit <= 1; uart_ptr <= uart_ptr + 1; end end endcase end endmodule