From 46a95fd39e0ef114dd837bed285f8ca6acf6bb32 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Tue, 23 Apr 2019 21:00:04 +0300 Subject: [PATCH] Make it work --- Makefile | 26 ++++--- addtest.pl | 17 +++++ asm.pm | 77 +++++++++++++++------ bigone.pl | 160 +++++++++++++++++++++++++++++++++++++++++++ chip.v | 21 +----- i2c.v | 97 ++++++++++++++++++-------- id.pl | 24 +++++++ ledmatrix.pl | 19 ++++++ master.pcf | 6 ++ master.v | 174 +++++++++++++++++++++++++++++++++++------------ master_rom.v | 24 ++----- news.v | 16 +++-- newstable.pl | 13 ++-- progall.sh | 4 ++ tinyledmatrix.pl | 28 ++++++++ uart.v | 4 +- worker.pcf | 19 ++++++ worker.v | 128 ++++++++++++++++++++++------------ 18 files changed, 662 insertions(+), 195 deletions(-) create mode 100644 addtest.pl create mode 100644 bigone.pl create mode 100644 id.pl create mode 100644 ledmatrix.pl create mode 100644 progall.sh create mode 100644 tinyledmatrix.pl create mode 100644 worker.pcf diff --git a/Makefile b/Makefile index e2c55e5..1b88b5c 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,17 @@ -PROJ = master -PIN_DEF = master.pcf DEVICE = hx1k -all: $(PROJ).rpt $(PROJ).bin +all: toplevel.bin -%.blif: %.v +toplevel.bin: master.rpt master.bin worker.rpt worker.bin + tools/icestorm/icemulti/icemulti -o toplevel.bin -v -p0 worker.bin master.bin + +master.blif: master.v tools/yosys/yosys -p 'synth_ice40 -top master -blif $@' $< -%.asc: $(PIN_DEF) %.blif +worker.blif: worker.v + tools/yosys/yosys -p 'synth_ice40 -top worker -blif $@' $< + +%.asc: %.pcf %.blif tools/arachne-pnr/bin/arachne-pnr -d $(subst hx,,$(subst lp,,$(DEVICE))) -o $@ -p $^ -P tq144 %.bin: %.asc @@ -16,14 +20,20 @@ all: $(PROJ).rpt $(PROJ).bin %.rpt: %.asc tools/icestorm/icetime/icetime -C tools/icestorm/icebox/chipdb-$(subst hx,,$(subst lp,,$(DEVICE))).txt -d $(DEVICE) -mtr $@ $< -prog: $(PROJ).bin +prog: toplevel.bin + tools/icestorm/iceprog/iceprog $< + +progall: toplevel.bin + bash progall.sh + +progmaster: master.bin tools/icestorm/iceprog/iceprog $< clean: - rm -f $(PROJ).blif $(PROJ).asc $(PROJ).bin + rm -f master.blif master.asc worker.blif worker.asc master.bin worker.bin toplevel.bin sim: - tools/yosys/yosys -p 'read_verilog -sv -DSIM master.v; prep -top master -nordff; sim -clock CLKin -vcd test.vcd -n 3000' + tools/yosys/yosys -p 'read_verilog -sv -DSIM worker.v; prep -top worker -nordff; sim -clock CLKin -vcd test.vcd -n 3000' .PHONY: all prog clean sim diff --git a/addtest.pl b/addtest.pl new file mode 100644 index 0000000..a43a4e1 --- /dev/null +++ b/addtest.pl @@ -0,0 +1,17 @@ +#!/usr/bin/perl +use v5.14; +use warnings; +use lib '.'; + +use asm; + +sub flag_to_memory { + my ($address, $flag) = @_; + alu3 alu_zero, alu_select_f, 0, 0, $address, $flag, flag_zero; +} + +storei 0, 5; +storei 1, 7; + +add 0, 1, 0, 4; +flag_to_memory 1, 4; diff --git a/asm.pm b/asm.pm index 269b8d1..1b6dc8a 100644 --- a/asm.pm +++ b/asm.pm @@ -36,8 +36,8 @@ my $port; use parent qw/Exporter/; -our @EXPORT = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC loadi storei ledm ledi route/; -our @EXPORT_OK = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC loadi storei ledm ledi route/; +our @EXPORT = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC loadi storei ledm ledi route chip_select/; +our @EXPORT_OK = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC loadi storei ledm ledi route chip_select/; use File::Slurp::Tiny 'write_file'; @@ -70,20 +70,30 @@ sub send__ { my $rom_cnt = 0; +# by default instructions are for all 4 chips to execute +our $CS = 0xF; + sub send_ { my ($cmd) = @_; my %cmd = %$cmd; + my $op_cs = $cmd{op} + ($CS << 4); - my $binary = pack 'vCC', @cmd{qw/I mem_addr op/}; # we ignore CS for now + my $binary = pack 'vCC', $cmd{I}, $cmd{mem_addr}, $op_cs; my $hex = reverse unpack 'h*', $binary; - say "$rom_cnt: data <= 32'h$hex;"; + # say "$rom_cnt: data <= 32'h$hex;"; + say $hex; $rom_cnt++; } +sub chip_select { + my ($new_cs, $sub) = @_; + local $CS = $new_cs; + $sub->(); +} sub nop { send_ - { I => 0, mem_addr => 0, op => OP_NOP, CS => 0 } + { I => 0, mem_addr => 0, op => OP_NOP } } sub loada { @@ -93,7 +103,7 @@ sub loada { $I |= $bsel << 4; $I |= $aluc << 5; send_ - { I => $I, mem_addr => $addr, op => OP_LOADA, CS => 0 } + { I => $I, mem_addr => $addr, op => OP_LOADA } } sub loadb { @@ -103,7 +113,7 @@ sub loadb { $I |= $inv << 4; $I |= $alus << 5; send_ - { I => $I, mem_addr => $addr, op => OP_LOADB, CS => 0 } + { I => $I, mem_addr => $addr, op => OP_LOADB } } #sub read_ { @@ -118,26 +128,28 @@ sub store { $I |= $edge_ << 7; $I |= $cube << 8; send_ - { I => $I, mem_addr => $addr, op => OP_STORE, CS => 0 } + { I => $I, mem_addr => $addr, op => OP_STORE } } sub loadi { my ($addr, $I) = @_; send_ - { I => $I, mem_addr => $addr, op => OP_LOADI, CS => 0 } + { I => $I, mem_addr => $addr, op => OP_LOADI } } sub route { - my ($addr, $dest_addr) = @_; + my ($addr, $dest_addr, $led) = @_; + $led //= 0; my $I = $dest_addr; + $I |= $led << 12; send_ - { I => $I, mem_addr => $addr, op => OP_ROUTE, CS => 0 } + { I => $I, mem_addr => $addr, op => OP_ROUTE } } sub storei { my ($addr, $I) = @_; send_ - { I => $I, mem_addr => $addr, op => OP_STOREI, CS => 0 } + { I => $I, mem_addr => $addr, op => OP_STOREI } } sub led { @@ -145,11 +157,12 @@ sub led { my $I = $offset_leds; $I |= $mode << 4; send_ - { I => $I, mem_addr => $addr, op => OP_LED, CS => 0 } + { I => $I, mem_addr => $addr, op => OP_LED } } sub ledm { my ($addr, $offset) = @_; + $offset //= 0; led $addr, 1, $offset; } @@ -207,6 +220,13 @@ sub alus_addAF { alu_of_function { ($a + $_) & 1 } } sub alu_or { alu_of_function { $a | $b | $_ } } +sub alu_and { alu_of_function { $a & $b & $_ } } + +BEGIN { + die "alus_add != alu_xor" unless alus_add == alu_xor; + die "bad alu_select_f" unless alu_select_f == alu_of_function { $_ }; +} + sub alu2 { my ($aluc, $alus, $addrA, $addrB, $flagr, $flagw, $cond, $inv) = @_; loada $addrA, $flagr, 0, $aluc; @@ -221,6 +241,11 @@ sub alu3 { store $addrC, $flagw, 0, 0; } +sub mov { + my ($addrA, $addrC) = @_; + alu3 alu_zero, alu_select_a, $addrA, $addrA, $addrC, flag_zero, flag_zero +} + sub add { my ($addrA, $addrB, $addrC, $flag_carry) = @_; alu3 aluc_add, alus_add, $addrA, $addrB, $addrC, flag_zero, $flag_carry; @@ -231,6 +256,16 @@ sub addC { alu3 aluc_add, alus_add, $addrA, $addrB, $addrC, $flag_carry, $flag_carry; } +sub xor_ { + my ($addrA, $addrB, $addrC) = @_; + alu3 alu_zero, alu_xor, $addrA, $addrB, $addrC, flag_zero, flag_zero; +} + +sub and_ { + my ($addrA, $addrB, $addrC) = @_; + alu3 alu_zero, alu_and, $addrA, $addrB, $addrC, flag_zero, flag_zero; +} + # news_gen face partea de mijloc # news_[mf][mf] face primul alu3, apeleaza news_gen, apoi face ultimul alu3 sub news_generic { @@ -238,16 +273,18 @@ sub news_generic { my %dest = %$dest; while ($nX || $nY) { my $direction; - if ($nX && $nY) { - $nX--; - $nY--; - $direction = 7; - } elsif ($nX) { + if ($nX > 0) { $nX--; + $direction = 2; + } elsif ($nX < 0) { + $nX++; $direction = 0; - } else { + } elsif ($nY > 0) { $nY--; - $direction = 6; + $direction = 1; + } elsif ($nY < 0) { + $nY++; + $direction = 3; } if ($nX || $nY) { # not the last go alu3 alu_select_f, alu_select_a, 0, 0, 0, flag_news($direction), flag_zero diff --git a/bigone.pl b/bigone.pl new file mode 100644 index 0000000..e4c3008 --- /dev/null +++ b/bigone.pl @@ -0,0 +1,160 @@ +#!/usr/bin/perl +use v5.14; +use warnings; +use lib '.'; + +use asm; + +sub update_leds { + my ($x) = @_; + route $x + 0, $x + 1, 4; + route $x + 1, $x + 2, 3; + route $x + 2, $x + 3, 2; + route $x + 3, $x + 4, 1; +} + +sub xori { + my ($addrA, $imm, $addrC) = @_; + storei 42, $imm; + xor_ $addrA, 42, $addrC; +} + +sub andi { + my ($addrA, $imm, $addrC) = @_; + storei 42, $imm; + and_ $addrA, 42, $addrC; +} + +# we want everyone to have +# +# own quadrant at mem[0] +# east quadrant at mem[11] +# south quadrant at mem[12] +# SE quadrant at mem[13] + +my $q_east = 11; +my $q_south = 12; +my $q_SE = 13; + +chip_select 4, sub { storei 0, 0x247 }; # glider +chip_select $_, sub { ledi $_ } for 1, 2, 4, 8; + + +update_leds 0; + +chip_select 1, sub { route 0, 11 }; +chip_select 2, sub { route 11, 12 }; +chip_select 4, sub { route 12, 13 }; + +chip_select 2, sub { route 0, 13 }; +chip_select 4, sub { route 13, 12 }; +chip_select 8, sub { route 12, 11 }; + +chip_select 4, sub { route 0, 11 }; +chip_select 8, sub { route 11, 12 }; +chip_select 1, sub { route 12, 13 }; + +chip_select 8, sub { route 0, 13 }; +chip_select 1, sub { route 13, 12 }; +chip_select 2, sub { route 12, 11 }; + + +sub news_to_mem { + my ($dir, $mem) = @_; + alu3 alu_zero, alu_select_f, 0, 0, $mem, flag_news($dir), flag_zero +} + +my $and_AB = alu_of_function { $a & $b }; + +sub compute_neighbour { + my ($dest, $dir, $mask, $other) = @_; + storei $dest, $mask; + alu3 $and_AB, $and_AB, 0, $dest, $dest, flag_zero, flag_zero; + news_to_mem $dir, $dest; + + storei $dest + 1, 0xFFFF - $mask; + alu3 $and_AB, $and_AB, $other, $dest + 1, $dest + 1, flag_zero, flag_zero; + alu3 alu_zero, alus_addAF, $dest, 0, $dest, flag_news($dir), flag_zero +} + +# N neighbour +compute_neighbour 1, 0, 0x0FFF, $q_south; +# E neighbour +compute_neighbour 2, 1, 0xEEEE, $q_east; +# S neighbour +compute_neighbour 3, 2, 0xFFF0, $q_south; +# W neighbour +compute_neighbour 4, 3, 0x7777, $q_east; + +sub compute_diagonal_neighbour { + my ($dest, $dir, @masks) = @_; + die 'expected exactly 4 @masks' unless @masks == 4; + storei $dest, $masks[0]; + alu3 $and_AB, alu_select_a, 0, $dest, 0, flag_zero, flag_zero; + news_to_mem $dir, $dest; + + for my $quad (1 .. 3) { + storei $dest + 1, $masks[$quad]; + alu3 $and_AB, alu_select_a, 10 + $quad, $dest + 1, 10 + $quad, flag_zero, flag_zero; + alu3 alu_zero, alus_addAF, $dest, 0, $dest, flag_news($dir), flag_zero; + } +} + +#update_leds $q_SE; + +# NW neighbour +compute_diagonal_neighbour 5, 4, 0x0777, 0x0888, 0x7000, 0x8000; +#update_leds 5; +# NE neighbour +compute_diagonal_neighbour 6, 5, 0x0EEE, 0x0111, 0xE000, 0x1000; +#update_leds 6; +# SE neighbour +compute_diagonal_neighbour 7, 6, 0xEEE0, 0x1110, 0x000E, 0x0001; +#update_leds 7; +# SW neighbour (DODGY) +compute_diagonal_neighbour 8, 7, 0x7770, 0x8880, 0x0007, 0x0008; +#update_leds 8; + +sub flag_to_memory { + my ($address, $flag) = @_; + alu3 alu_zero, alu_select_f, 0, 0, $address, $flag, flag_zero; +} + +# now we add bits mem[1] .. mem[8] +# result should be mem[1] .. mem[3] (we don't distinguish 8 from 0) +my $F = 1; + +# add 1 and 2, 3 and 4, 5 and 6, 7 and 8 +for my $x (1, 3, 5, 7) { + add $x, $x + 1, $x, $F; + flag_to_memory $x + 1, $F; +} + +# add 12 and 34, 56 and 78 +for my $x (1, 5) { + add $x, $x + 2, $x, $F; + addC $x + 1, $x + 3, $x + 1, $F; + flag_to_memory $x + 2, $F; +} + +# add 12 and 56 +add 1, 5, 1, $F; +addC 2, 6, 2, $F; +# F = F | 3 | 7 +alu3 alu_or, alu_select_a, 3, 7, 3, $F, $F; + +# should a new cell be born here? (do we have 3 neighbours?) +sub alu_birth { alu_of_function {; $a && $b && !$_ } } + +# should a living cell survive here? (do we have 2 or 3 neighbours?) +sub alu_survival { alu_of_function {; $a && !$_ } } + +# compute the state of this cell at the next tick +sub alu_step { alu_of_function {; $_ & ($a | $b) } } + +# read from memory 1, and with memory 2 and not F, write into memory 1 (= birth-p) +alu3 alu_zero, alu_birth, 1, 2, 1, $F, flag_zero; +# read from memory 2, and with flag not F, write into flag F (= survive-p) +alu3 alu_survival, alu_select_a, 2, 0, 2, $F, $F; +# read from memory 0, memory 1, and flag F, write F and (mem0 or mem1) into memory 0 +alu3 alu_zero, alu_step, 0, 1, 0, $F, $F; # also zeroes out flag F diff --git a/chip.v b/chip.v index 1ff0d50..1200640 100644 --- a/chip.v +++ b/chip.v @@ -18,7 +18,7 @@ `define DIRECTION_W 3'd6 `define DIRECTION_NW 3'd7 -module chip(input clk, input [2:0] op, input [15:0] I, input io_pin, input CS, output reg [15:0] mem_in, input [15:0] mem_out, output reg mem_write, output reg [3:0] led_out = 0); +module chip(input clk, input [2:0] op, input [15:0] I, output reg [15:0] mem_in, input [15:0] mem_out, output reg mem_write, output reg [3:0] led_out = 0); // parity is unimplemented @@ -37,19 +37,6 @@ module chip(input clk, input [2:0] op, input [15:0] I, input io_pin, input CS, o wire edge_ = I[7]; wire [3:0] cube = I[11:8]; - // OP_ROUTE - wire [5:0] cycle = I[5:0]; - wire [1:0] check = I[7:6]; - wire [3:0] xor_ = I[11:8]; - wire [2:0] snarf = I[14:12]; - wire odd = I[15]; - - // OP_RUG - wire rw = I[0]; - wire ac = I[1]; - wire news = I[2]; - wire [4:0] reg_ = I[8:4]; - // OP_LED wire mode = I[4]; wire [1:0] offset = I[1:0]; @@ -65,14 +52,13 @@ module chip(input clk, input [2:0] op, input [15:0] I, input io_pin, input CS, o reg [7:0] alu_sum = 0; reg [7:0] alu_carry = 0; reg [15:0] cube_in; - reg io; // these are not really regs reg [15:0] alu_sum_out; reg [15:0] alu_carry_out; - reg [2:0] alu_index [15:0]; + reg [2:0] alu_index [15:0]; reg [15:0] idx; @@ -114,7 +100,7 @@ module chip(input clk, input [2:0] op, input [15:0] I, input io_pin, input CS, o reg [15:0] flag_or_news; reg [15:0] news_out; - news newspaper (.news_in(latest_news), .direction(flags_addr[1:0]), .news_out(news_out)); + news newspaper (.news_in(latest_news), .direction(flags_addr[2:0]), .news_out(news_out)); assign flag_or_news = flags_addr[3] ? news_out : flags_out; @@ -135,7 +121,6 @@ module chip(input clk, input [2:0] op, input [15:0] I, input io_pin, input CS, o F <= flag_or_news; A <= mem_out; C <= mem_out; - io <= io_pin; if (bsel) B <= cube_in; end diff --git a/i2c.v b/i2c.v index 6815617..9620ba0 100644 --- a/i2c.v +++ b/i2c.v @@ -15,12 +15,13 @@ parameter CLOCK_DIVIDE = 1; // We transmit a START, then the address (constant 0xE1), then // [tx_byte], then [more_bytes] bytes from [mb_in] parameter TX_IDLE = 0; -parameter TX_ADDRESS = 1; -parameter TX_FIRST_BYTE = 2; -parameter TX_MORE_BYTES = 3; -parameter TX_STOP = 4; +parameter TX_START = 1; +parameter TX_ADDRESS = 2; +parameter TX_FIRST_BYTE = 3; +parameter TX_MORE_BYTES = 4; +parameter TX_STOP = 5; -reg [10:0] tx_clk_divider = CLOCK_DIVIDE; +reg [30:0] tx_clk_divider = CLOCK_DIVIDE; reg data_out = 1'b1; reg clk_out = 1'b1; @@ -31,6 +32,7 @@ reg [3:0] tx_bits_remaining; reg [7:0] tx_data; reg [3:0] step = 0; +reg [5:0] more_bytes_idx = 0; wire [7:0] address = {7'h70, 1'b0}; // address 0x70, write wire [15:0] address_data = {address, tx_data}; @@ -38,37 +40,37 @@ wire [15:0] address_data = {address, tx_data}; assign sda = data_out; assign scl = clk_out; assign is_transmitting = tx_state != TX_IDLE; +assign mb_addr = more_bytes_idx; always @(posedge clk) begin - // The clk_divider counter counts down from - // the CLOCK_DIVIDE constant. Whenever it - // reaches 0, 1/16 of the bit period has elapsed. - // Countdown timers for the receiving and transmitting - // state machines are decremented. - tx_clk_divider = tx_clk_divider - 1; - if (!tx_clk_divider) begin - tx_clk_divider = CLOCK_DIVIDE; - tx_countdown = tx_countdown - 1; - end - - // Transmit state machine - case (tx_state) + if(tx_clk_divider) begin + tx_clk_divider <= tx_clk_divider - 1; + end else begin + tx_clk_divider <= CLOCK_DIVIDE - 1; + end + + case (tx_state) TX_IDLE: begin if (transmit) begin - // If the transmit flag is raised in the idle - // state, save tx_byte for transmission tx_data = tx_byte; - // Send the initial, low pulse of 1 bit period - // to signal the start, followed by the data - data_out = 0; - tx_state = TX_ADDRESS; tx_bits_remaining = 8; step = 0; + tx_state = TX_START; + tx_clk_divider <= CLOCK_DIVIDE - 1; end end // case: TX_IDLE + TX_START: begin + if(tx_clk_divider) begin end + else begin + data_out = 0; + tx_state = TX_ADDRESS; + end + end + TX_ADDRESS: begin - if(step == 0) begin + if(tx_clk_divider) begin end + else if(step == 0) begin clk_out <= 0; step <= 1; end else if (tx_bits_remaining == 0) begin @@ -97,7 +99,8 @@ always @(posedge clk) begin end // case: TX_ADDRESS TX_FIRST_BYTE: begin - if(step == 0) begin + if(tx_clk_divider) begin end + else if(step == 0) begin clk_out <= 0; step <= 1; end else if (tx_bits_remaining == 0) begin @@ -110,7 +113,12 @@ always @(posedge clk) begin end else begin step <= 0; - tx_state <= TX_STOP; + if(more_bytes) + tx_state <= TX_MORE_BYTES; + else + tx_state <= TX_STOP; + tx_bits_remaining <= 8; + more_bytes_idx <= 0; end end else if(step == 1) begin data_out <= tx_data[tx_bits_remaining - 1]; @@ -124,8 +132,41 @@ always @(posedge clk) begin end end // case: TX_FIRST_BYTE + TX_MORE_BYTES: begin + if(tx_clk_divider) begin end + else if(step == 0) begin + clk_out <= 0; + step <= 1; + end else if (tx_bits_remaining == 0) begin + if(step == 1) begin + data_out <= 0; // really should be z, not 0 + step <= 2; + end else if(step == 2)begin + clk_out <= 1; + step <= 3; + end else begin + step <= 0; + tx_bits_remaining <= 8; + + if(more_bytes_idx == more_bytes) + tx_state <= TX_STOP; + more_bytes_idx <= more_bytes_idx + 1; + end + end else if(step == 1) begin + data_out <= mb_in[tx_bits_remaining - 1]; + step <= 2; + end else if(step == 2) begin + clk_out <= 1; + step <= 3; + end else begin // step == 3 + tx_bits_remaining = tx_bits_remaining - 1; + step <= 0; + end + end // case: TX_MORE_BYTES + TX_STOP: begin - if(step == 0) begin + if(tx_clk_divider) begin end + else if(step == 0) begin clk_out <= 0; step <= 1; end else if(step == 1) begin diff --git a/id.pl b/id.pl new file mode 100644 index 0000000..3f03d73 --- /dev/null +++ b/id.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl +use v5.14; +use warnings; +use lib '.'; + +use asm; + +chip_select 1, sub { + storei 0, 0x3; +}; + +chip_select 2, sub { + storei 0, 0x2; +}; + +chip_select 4, sub { + storei 0, 0x4; +}; + +chip_select 8, sub { + storei 0, 0x8; +}; + +ledm 0; diff --git a/ledmatrix.pl b/ledmatrix.pl new file mode 100644 index 0000000..576fe92 --- /dev/null +++ b/ledmatrix.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl +use v5.14; +use warnings; +use lib '.'; + +use asm; + +storei 0, 0xF; +route 0, 9, 1; +ledi 1; +news_mm 0, 1, -1, 0; +route 1, 9, 1; +ledi 2; +news_mm 1, 2, -1, 0; +route 2, 9, 1; +ledi 4; +news_mm 2, 3, -1, 0; +route 3, 9, 1; +ledi 8; diff --git a/master.pcf b/master.pcf index 037381f..b2de457 100644 --- a/master.pcf +++ b/master.pcf @@ -10,6 +10,12 @@ set_io led[4] 95 # 12 MHz clock set_io CLKin 21 +set_io uart_tx 79 +set_io -pullup yes uart_rx 88 + +set_io busy_out 87 +set_io -pullup yes busy_in 78 + # i2c to led matrix set_io scl 80 # PIO1_04 set_io sda 81 # PIO1_05 diff --git a/master.v b/master.v index f76bfb1..a009ce2 100644 --- a/master.v +++ b/master.v @@ -1,47 +1,112 @@ +`include "pll.v" `include "master_rom.v" `include "i2c.v" `include "uart.v" `ifdef SIM `define UART_DIVIDE 1 + `define I2C_DIVIDE 4 `else - `define UART_DIVIDE 1 - // s/192/3/ for 19200 baud uart + `define UART_DIVIDE 2048 + `define I2C_DIVIDE 256 `endif -module master(input CLKin, output [4:0] led, output uart_tx, input uart_rx, output reg ready_out = 1, input ready_in, output scl, output sda); -// wire clk; -// wire clk_tmp; +module master(input CLKin, output [4:0] led, output uart_tx, input uart_rx, output reg busy_out = 0, input busy_in, output scl, output sda); + wire clk; - //pll pll (.clock_in(CLKin), .clock_out(clk)); + assign clk = CLKin; - reg [20:0] counter = 0; + // ROM -`ifdef SIM - wire clk = CLKin; -`else - reg clk = 0; + reg [7:0] program_counter = 0; + // go here at end of program + reg [7:0] main = 1; + wire [31:0] rom_output; - always @ (posedge CLKin) begin - if(counter == 5000) begin - counter <= 0; - clk <= 1 - clk; - end - else - counter <= counter + 1; + master_rom master_rom (.clk(clk), .addr(program_counter), .data(rom_output)); + + wire [2:0] rom_op = rom_output[26:24]; + wire [2:0] rom_led = rom_output[14:12]; + wire [3:0] rom_chip_select = rom_output[31:28]; + + // if the 4th board won't execute this instruction, + // then we won't receive propagation or news + wire dont_wait = !rom_chip_select[3]; + reg [25:0] dont_send = 23'b11111111111111111111111; + + always @(posedge clk) begin + if(busy_in) + dont_send <= 23'b11111111111111111111111; + else if(dont_send) + dont_send <= dont_send - 1; end -`endif - reg [3:0] program_counter = 0; - wire [31:0] rom_output; + // state - master_rom master_rom (.clk(clk), .addr(program_counter), .data(rom_output)); +`define STATE_SEND 0 +`define STATE_WAIT_PROPAGATE 1 +`define STATE_WAIT_NEWS 2 +`define STATE_PROPAGATE_NEWS 3 +`define STATE_SET_LEDS 4 +`define STATE_WASTE_TIME 5 + + reg [5:0] state = `STATE_SEND; + reg [5:0] uart_ptr = 0; + + reg [30:0] waste_counter = 0; + reg [7:0] saved_news [3:0]; + reg [7:0] sent_byte [3:0]; + + reg [7:0] bytes_sent = 0; + + // i2c + reg [15:0] leds [3:0]; + + initial begin + leds[0] <= 16'hF00F; + leds[1] <= 16'h0000; + leds[2] <= 16'h0000; + leds[3] <= 16'hFFFF; + end + + /* even rows are green, odd rows are red: + * mb_leds[2 * k] is the kth row of green leds + * mb_leds[2 * k + 1] is the kth row of red leds + */ + wire [7:0] mb_leds [15:0]; + + // all red leds are off + assign mb_leds[1] = program_counter; + assign mb_leds[3] = 0; + assign mb_leds[5] = state; + assign mb_leds[7] = uart_ptr; + assign mb_leds[9] = 0; + assign mb_leds[11] = 0; + assign mb_leds[13] = 0; + assign mb_leds[15] = 0; + + // green leds, first half + assign mb_leds[0] = {leds[1][3:0], leds[0][3:0]}; + assign mb_leds[2] = {leds[1][7:4], leds[0][7:4]}; + assign mb_leds[4] = {leds[1][11:8], leds[0][11:8]}; + assign mb_leds[6] = {leds[1][15:12], leds[0][15:12]}; + + // green leds, second half + assign mb_leds[8] = {leds[3][3:0], leds[2][3:0]}; + assign mb_leds[10] = {leds[3][7:4], leds[2][7:4]}; + assign mb_leds[12] = {leds[3][11:8], leds[2][11:8]}; + assign mb_leds[14] = {leds[3][15:12], leds[2][15:12]}; + + wire [7:0] mb_in; + wire [5:0] mb_addr; + assign mb_in = mb_leds[mb_addr]; reg [7:0] i2c_tx_byte; + reg [5:0] more_bytes = 0; reg i2c_transmit = 0; wire i2c_is_transmitting; - i2c_write i2c (.clk(clk), .scl(scl), .sda(sda), .tx_byte(i2c_tx_byte), .transmit(i2c_transmit), .is_transmitting(i2c_is_transmitting)); + i2c_write #(.CLOCK_DIVIDE(`I2C_DIVIDE)) i2c (.clk(clk), .scl(scl), .sda(sda), .tx_byte(i2c_tx_byte), .transmit(i2c_transmit), .is_transmitting(i2c_is_transmitting), .more_bytes(more_bytes), .mb_in(mb_in), .mb_addr(mb_addr)); reg [3:0] i2c_init_step = 0; @@ -54,27 +119,25 @@ module master(input CLKin, output [4:0] led, output uart_tx, input uart_rx, outp i2c_transmit <= 1; i2c_init_step <= 1; end else if(i2c_init_step == 1) begin - i2c_tx_byte <= 8'h87; // display on, blink 0.5Hz + i2c_tx_byte <= 8'h81; // display on, blink off i2c_transmit <= 1; i2c_init_step <= 2; end else if(i2c_init_step == 2) begin i2c_tx_byte <= 8'hEF; // max brightness i2c_transmit <= 1; i2c_init_step <= 3; + end else if(i2c_init_step == 3) begin + i2c_tx_byte <= 0; + more_bytes <= 16; + i2c_transmit <= 1; + i2c_init_step <= 4; + end else begin + i2c_transmit <= 1; end end end -`define STATE_SEND 0 -`define STATE_WAIT_PROPAGATE 1 -`define STATE_WAIT_NEWS 2 -`define STATE_PROPAGATE_NEWS 3 -`define STATE_WASTE_TIME 4 - - reg [5:0] state = `STATE_SEND; - reg [5:0] uart_ptr = 0; - wire received; wire [7:0] rx_byte; reg transmit = 0; @@ -82,15 +145,22 @@ module master(input CLKin, output [4:0] led, output uart_tx, input uart_rx, outp wire is_receiving; wire is_transmitting; - // 19200 (actually 300) baud uart 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)); - reg [15:0] waste_counter = 0; + assign led[4] = state != `STATE_WASTE_TIME; +// assign led[2:0] = rom_op == 6 ? rom_led : 0; +// assign led[3] = refresh_leds || i2c_is_transmitting; +// assign led[0] = (leds[0] == 16'h000f); +// assign led[1] = (leds[0] == 16'h00f0); +// assign led[2] = (leds[0] == 16'h0111); +// assign led[3] = (leds[0] == 16'hf00f); - reg [7:0] saved_news [3:0]; - assign led[4] = state != `STATE_WASTE_TIME; - assign led[3:0] = i2c_init_step; + //assign led[3:0] = saved_news[0][3:0]; + //assign led[3:0] = program_counter[3:0]; + assign led[0] = dont_send; + assign led[1] = dont_wait; + assign led[2] = is_transmitting; always @(posedge clk) begin case(state) @@ -98,15 +168,18 @@ module master(input CLKin, output [4:0] led, output uart_tx, input uart_rx, outp if(transmit) begin transmit <= 0; end else if(uart_ptr == 4) begin - program_counter <= program_counter + 1; uart_ptr <= 0; - if(rom_output[26:24] == 6) // `OP_ROUTE + if(dont_wait) + state <= `STATE_WASTE_TIME; + else if(rom_op == 6) // `OP_ROUTE state <= `STATE_WAIT_NEWS; else state <= `STATE_WAIT_PROPAGATE; - end else if(!is_transmitting && ready_in) begin + end else if(!is_transmitting && !dont_send) begin tx_byte <= rom_output[uart_ptr * 8 +: 8]; + sent_byte[uart_ptr] <= rom_output[uart_ptr * 8 +: 8]; transmit <= 1; + bytes_sent <= bytes_sent + 1; uart_ptr <= uart_ptr + 1; end end @@ -118,8 +191,12 @@ module master(input CLKin, output [4:0] led, output uart_tx, input uart_rx, outp end `STATE_WASTE_TIME: begin - if(waste_counter == 100) begin + if(waste_counter == 50000) begin waste_counter <= 0; + if(program_counter == 255) + program_counter <= main; + else + program_counter <= program_counter + 1; state <= `STATE_SEND; end else waste_counter <= waste_counter + 1; @@ -143,15 +220,22 @@ module master(input CLKin, output [4:0] led, output uart_tx, input uart_rx, outp end // case: `STATE_WAIT_NEWS `STATE_PROPAGATE_NEWS: begin - if(uart_ptr == 4) begin + if(transmit) begin + transmit <= 0; + end else if(uart_ptr == 4) begin + if(rom_led) begin + leds[rom_led - 1] <= (saved_news[1] << 8) + saved_news[0]; + end state <= `STATE_WASTE_TIME; uart_ptr <= 0; - end else if(!is_transmitting && ready_in) begin + end else if(!is_transmitting && !dont_send) begin tx_byte <= saved_news[uart_ptr]; + sent_byte[uart_ptr] <= saved_news[uart_ptr]; transmit <= 1; + bytes_sent <= bytes_sent + 1; uart_ptr <= uart_ptr + 1; end - end + end // case: `STATE_PROPAGATE_NEWS endcase end diff --git a/master_rom.v b/master_rom.v index 0fc52dd..a088c87 100644 --- a/master_rom.v +++ b/master_rom.v @@ -1,25 +1,11 @@ // ROM module with single input addr, output port, and clock input. // Data is clocked out of the ROM on positive clock edges. -module master_rom (input clk, input [3:0] addr, output reg [31:0] data); +module master_rom (input clk, input [7:0] addr, output reg [31:0] data); + reg [31:0] rom [0:255]; + initial $readmemh("code.hex", rom); + always @ (posedge clk) begin - case(addr) -0: data <= 32'h04000004; -1: data <= 32'h04010002; -2: data <= 32'h07010010; -3: data <= 32'h00000000; -4: data <= 32'h00000000; -5: data <= 32'h06000001; -6: data <= 32'h07010010; -7: data <= 32'h00000000; -8: data <= 32'h00000000; -9: data <= 32'h04010003; -10: data <= 32'h07010010; -11: data <= 32'h00000000; -12: data <= 32'h00000000; -13: data <= 32'h06000001; -14: data <= 32'h07010010; -15: data <= 32'h00000000; - endcase + data <= rom[addr]; end endmodule diff --git a/news.v b/news.v index b0d34a7..73c7507 100644 --- a/news.v +++ b/news.v @@ -1,10 +1,14 @@ -module news(input clk, input [15:0] news_in, input [1:0] direction, output [15:0] news_out); - always @(posedge clk) begin +module news(input clk, input [15:0] news_in, input [2:0] direction, output [0:15] news_out); + always @* begin case (direction) -0: news_out = {news_in[12], news_in[13], news_in[14], news_in[15], news_in[ 0], news_in[ 1], news_in[ 2], news_in[ 3], news_in[ 4], news_in[ 5], news_in[ 6], news_in[ 7], news_in[ 8], news_in[ 9], news_in[10], news_in[11]}; -1: news_out = {news_in[ 1], news_in[ 2], news_in[ 3], news_in[ 0], news_in[ 5], news_in[ 6], news_in[ 7], news_in[ 4], news_in[ 9], news_in[10], news_in[11], news_in[ 8], news_in[13], news_in[14], news_in[15], news_in[12]}; -2: news_out = {news_in[ 4], news_in[ 5], news_in[ 6], news_in[ 7], news_in[ 8], news_in[ 9], news_in[10], news_in[11], news_in[12], news_in[13], news_in[14], news_in[15], news_in[ 0], news_in[ 1], news_in[ 2], news_in[ 3]}; -3: news_out = {news_in[ 3], news_in[ 0], news_in[ 1], news_in[ 2], news_in[ 7], news_in[ 4], news_in[ 5], news_in[ 6], news_in[11], news_in[ 8], news_in[ 9], news_in[10], news_in[15], news_in[12], news_in[13], news_in[14]}; +0: news_out = {news_in[11], news_in[10], news_in[ 9], news_in[ 8], news_in[ 7], news_in[ 6], news_in[ 5], news_in[ 4], news_in[ 3], news_in[ 2], news_in[ 1], news_in[ 0], news_in[15], news_in[14], news_in[13], news_in[12]}; +1: news_out = {news_in[12], news_in[15], news_in[14], news_in[13], news_in[ 8], news_in[11], news_in[10], news_in[ 9], news_in[ 4], news_in[ 7], news_in[ 6], news_in[ 5], news_in[ 0], news_in[ 3], news_in[ 2], news_in[ 1]}; +2: news_out = {news_in[ 3], news_in[ 2], news_in[ 1], news_in[ 0], news_in[15], news_in[14], news_in[13], news_in[12], news_in[11], news_in[10], news_in[ 9], news_in[ 8], news_in[ 7], news_in[ 6], news_in[ 5], news_in[ 4]}; +3: news_out = {news_in[14], news_in[13], news_in[12], news_in[15], news_in[10], news_in[ 9], news_in[ 8], news_in[11], news_in[ 6], news_in[ 5], news_in[ 4], news_in[ 7], news_in[ 2], news_in[ 1], news_in[ 0], news_in[ 3]}; +4: news_out = {news_in[10], news_in[ 9], news_in[ 8], news_in[11], news_in[ 6], news_in[ 5], news_in[ 4], news_in[ 7], news_in[ 2], news_in[ 1], news_in[ 0], news_in[ 3], news_in[14], news_in[13], news_in[12], news_in[15]}; +5: news_out = {news_in[ 8], news_in[11], news_in[10], news_in[ 9], news_in[ 4], news_in[ 7], news_in[ 6], news_in[ 5], news_in[ 0], news_in[ 3], news_in[ 2], news_in[ 1], news_in[12], news_in[15], news_in[14], news_in[13]}; +6: news_out = {news_in[ 0], news_in[ 3], news_in[ 2], news_in[ 1], news_in[12], news_in[15], news_in[14], news_in[13], news_in[ 8], news_in[11], news_in[10], news_in[ 9], news_in[ 4], news_in[ 7], news_in[ 6], news_in[ 5]}; +7: news_out = {news_in[ 2], news_in[ 1], news_in[ 0], news_in[ 3], news_in[14], news_in[13], news_in[12], news_in[15], news_in[10], news_in[ 9], news_in[ 8], news_in[11], news_in[ 6], news_in[ 5], news_in[ 4], news_in[ 7]}; endcase end diff --git a/newstable.pl b/newstable.pl index cbfbbd7..67957b8 100644 --- a/newstable.pl +++ b/newstable.pl @@ -4,13 +4,13 @@ use warnings; my @diffs = ( [-1, 0], -# [-1, 1], [0 , 1], -# [1 , 1], [1 , 0], -# [1 , -1], [0 , -1], -# [-1, -1] + [-1, -1], + [-1, 1], + [1 , 1], + [1 , -1], ); my @cpus; @@ -35,8 +35,9 @@ for my $cpu (0 .. ($side * $side - 1)) { for my $direction (0 .. $#diffs) { print "$direction: news_out = {"; - printf 'news_in[%2d]', $newstable[0][$direction]; - for my $cpu (1 .. ($side * $side - 1)) { + printf 'news_in[%2d]', $newstable[$side * $side - 1][$direction]; + my @lst = 0 .. ($side * $side - 2); + for my $cpu (reverse @lst) { printf ', news_in[%2d]', $newstable[$cpu][$direction]; } say '};' diff --git a/progall.sh b/progall.sh new file mode 100644 index 0000000..9be606f --- /dev/null +++ b/progall.sh @@ -0,0 +1,4 @@ +#!/bin/bash +for i in `seq 1 $(lsusb | grep -c 6010)` +do tools/icestorm/iceprog/iceprog -d i:0x0403:0x6010:$(($i - 1)) toplevel.bin +done diff --git a/tinyledmatrix.pl b/tinyledmatrix.pl new file mode 100644 index 0000000..b1899ce --- /dev/null +++ b/tinyledmatrix.pl @@ -0,0 +1,28 @@ +#!/usr/bin/perl +use v5.14; +use warnings; +use lib '.'; + +use asm; + +storei 0, 0xF; +route 0, 1, 1; +nop; +nop; +nop; +nop; +nop; +storei 0, 0xF0; +route 0, 1, 1; +nop; +nop; +nop; +nop; +nop; +storei 0, 0x111; +route 0, 1, 1; +nop; +nop; +nop; +nop; +nop; diff --git a/uart.v b/uart.v index 6db3650..4db8881 100644 --- a/uart.v +++ b/uart.v @@ -53,8 +53,8 @@ parameter TX_IDLE = 0; parameter TX_SENDING = 1; parameter TX_DELAY_RESTART = 2; -reg [10:0] rx_clk_divider = CLOCK_DIVIDE; -reg [10:0] tx_clk_divider = CLOCK_DIVIDE; +reg [21:0] rx_clk_divider = CLOCK_DIVIDE; +reg [21:0] tx_clk_divider = CLOCK_DIVIDE; reg [2:0] recv_state = RX_IDLE; reg [5:0] rx_countdown; diff --git a/worker.pcf b/worker.pcf new file mode 100644 index 0000000..574efb6 --- /dev/null +++ b/worker.pcf @@ -0,0 +1,19 @@ +# Red LEDs +set_io led[0] 99 +set_io led[1] 98 +set_io led[2] 97 +set_io led[3] 96 + +# Green LED +set_io led[4] 95 + +# 12 MHz clock +set_io CLKin 21 + +set_io uart_tx 79 +set_io -pullup yes uart_rx 88 + +set_io busy_out 87 +set_io -pullup yes busy_in 78 + +set_io -pullup yes is_worker 91 \ No newline at end of file diff --git a/worker.v b/worker.v index e8552d0..9a7760e 100644 --- a/worker.v +++ b/worker.v @@ -6,34 +6,49 @@ `ifdef SIM `define UART_DIVIDE 1 `else - `define UART_DIVIDE 1 - // s/192/3/ for 19200 baud uart + `define UART_DIVIDE 2048 `endif -module worker (input CLKin, output [4:0] led, output uart_tx, input uart_rx, output reg ready_out = 1, input ready_in); - wire clk; - wire clk_tmp; - - //pll pll (.clock_in(CLKin), .clock_out(clk)); +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; - reg [20:0] counter = 0; +`ifndef SIM + // if [is_worker == 0], boot into master image + SB_WARMBOOT wb (.BOOT (!is_worker), .S0(1'b1), .S1(1'b0)); +`endif - reg clk = 0; +`ifdef SIM + wire dont_send = 0; +`else + reg [25:0] dont_send = 23'b11111111111111111111111; - always @ (posedge CLKin) begin - if(counter == 5000) begin - counter <= 0; - clk <= 1 - clk; - end - else - counter <= counter + 1; + always @(posedge clk) begin + if(busy_in) + dont_send <= 23'b11111111111111111111111; + 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]; @@ -42,7 +57,18 @@ module worker (input CLKin, output [4:0] led, output uart_tx, input uart_rx, out 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 CS = from_uart[3][3]; + + 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 @@ -51,18 +77,17 @@ module worker (input CLKin, output [4:0] led, output uart_tx, input uart_rx, out 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] = 3'd4; // OP_STOREI + 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 CS; reg [3:0] led_out; - chip chip (.clk(clk), .op(op), .I(I), .io_pin(0), .CS(CS), .mem_in(mem_in), .mem_out(mem_out), .mem_write(mem_write), .led_out(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; @@ -70,19 +95,20 @@ module worker (input CLKin, output [4:0] led, output uart_tx, input uart_rx, out reg [7:0] tx_byte = 0; wire is_receiving; wire is_transmitting; + wire recv_error; - // 19200 (actually 300) baud uart - 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)); + 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_EXECUTE 2 -`define STATE_ROUTE 3 +`define STATE_PREEXEC 2 +`define STATE_EXECUTE 3 +`define STATE_ROUTE 4 - reg [5:0] state = `STATE_IDLE; + reg [3:0] state = `STATE_IDLE; - assign led[3:0] = led_out; - assign led[4] = 0; + assign led[3:0] = uart_ptr; + assign led[4] = is_receiving; always @ (posedge clk) begin case(state) @@ -90,14 +116,27 @@ module worker (input CLKin, output [4:0] led, output uart_tx, input uart_rx, out if(uart_ptr == 4) begin last_op <= op_from_uart; uart_ptr <= 0; - state <= `STATE_PROPAGATE; - ready_out <= 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 - ready_out <= 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 @@ -105,18 +144,23 @@ module worker (input CLKin, output [4:0] led, output uart_tx, input uart_rx, out transmit <= 0; else if(uart_ptr == 4) begin uart_ptr <= 0; - the_leds <= last_op; - if(last_op == `OP_ROUTE) begin - state <= `STATE_ROUTE; - end else begin - op <= last_op; - state <= `STATE_EXECUTE; - end - end else if(!is_transmitting && ready_in) begin - tx_byte <= from_uart[uart_ptr]; + 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 @@ -130,7 +174,7 @@ module worker (input CLKin, output [4:0] led, output uart_tx, input uart_rx, out else if(uart_ptr == 4) begin uart_ptr <= 0; state <= `STATE_IDLE; - end else if(!is_transmitting && ready_in) begin + end else if(!is_transmitting && !dont_send) begin tx_byte <= route_storei[uart_ptr]; transmit <= 1; uart_ptr <= uart_ptr + 1; @@ -138,6 +182,4 @@ module worker (input CLKin, output [4:0] led, output uart_tx, input uart_rx, out end endcase end - -// wire ready = (state == 0 && !is_receiving); endmodule -- 2.39.2