Conway works (with sleeps)
authorMarius Gavrilescu <marius@ieval.ro>
Wed, 9 Jan 2019 12:29:59 +0000 (12:29 +0000)
committerMarius Gavrilescu <marius@ieval.ro>
Wed, 9 Jan 2019 12:29:59 +0000 (12:29 +0000)
Makefile
asm.pm [new file with mode: 0644]
cells.pl [new file with mode: 0644]
chip.v
intermediare.pl [new file with mode: 0644]
newstable.pl [new file with mode: 0644]
ram.v
toplevel.v
yosys-sim-script

index 64606370a5316b756a95158e6f162cf6fe53d260..0fb0a575be3498fa5c8ebb7dc58637598ad34449 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,4 +22,8 @@ prog: $(PROJ).bin
 clean:
        rm -f $(PROJ).blif $(PROJ).asc $(PROJ).bin
 
-.PHONY: all prog clean
+
+sim:
+       tools/yosys/yosys -p 'read_verilog -sv -DSIM toplevel.v; prep -top toplevel -nordff; sim -clock CLKin -vcd test.vcd -n 3000'
+
+.PHONY: all prog clean sim
diff --git a/asm.pm b/asm.pm
new file mode 100644 (file)
index 0000000..d07004e
--- /dev/null
+++ b/asm.pm
@@ -0,0 +1,174 @@
+#!/usr/bin/perl
+use v5.14;
+use warnings;
+
+use constant +{
+       OP_NOP => 0,
+       OP_LOADA => 1,
+       OP_LOADB => 2,
+       OP_STORE => 3,
+       OP_READ => 4,
+       OP_LOADI => 5,
+       OP_ROUTE => 6,
+       OP_RUG => 7,
+};
+
+q,
+use Device::SerialPort;
+
+my $port = Device::SerialPort->new($ARGV[0] // '/dev/ttyUSB1') or die "$!";
+$port->baudrate(300);
+#$port->baudrate(4000000);
+$port->parity('none');
+$port->databits(8);
+$port->stopbits(2);
+$port->handshake('none');
+$port->read_const_time(2000);
+
+$port->write_settings or die "$!";
+,;
+
+use Fcntl;
+use Time::HiRes qw/sleep/;
+
+sysopen my $port, '/dev/ttyUSB1', O_SYNC | O_RDWR or die "$!";
+
+
+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/;
+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/;
+
+use File::Slurp::Tiny 'write_file';
+
+sub send_ {
+       my ($cmd) = @_;
+       my %cmd = %$cmd;
+
+       my $binary = pack 'vCC', @cmd{qw/I mem_addr op/}; # we ignore CS for now
+       my $length = length $binary;
+       my $wrote = syswrite $port, $binary, $length;
+       sleep 0.2;
+#      say "Wrote $wrote of $length bytes";
+       if ($cmd{op} == OP_READ) {
+               my $string_in;
+               my $count_in = sysread $port, $string_in, 2;
+               my @memory = unpack 'v*', $string_in;
+               for (@memory) {
+                       printf "%X", $_
+               }
+               print " "
+       }
+}
+
+sub loada {
+       my ($addr, $flagr, $bsel, $aluc) = @_;
+       my $I = 0;
+       $I |= $flagr;
+       $I |= $bsel << 4;
+       $I |= $aluc << 5;
+       send_
+         { I => $I, mem_addr => $addr, op => OP_LOADA, CS => 0 }
+  }
+
+sub loadb {
+       my ($addr, $cond, $inv, $alus) = @_;
+       my $I = 0;
+       $I |= $cond;
+       $I |= $inv << 4;
+       $I |= $alus << 5;
+       send_
+         { I => $I, mem_addr => $addr, op => OP_LOADB, CS => 0 }
+  }
+
+sub read_ {
+       my ($addr) = @_;
+       send_ { I => 0, mem_addr => $addr, op => OP_READ, CS => 1 }
+}
+
+sub store {
+       my ($addr, $flagw, $edge_, $cube) = @_;
+       my $I = 0;
+       $I |= $flagw;
+       $I |= $edge_ << 7;
+       $I |= $cube << 8;
+       send_
+         { I => $I, mem_addr => $addr, op => OP_STORE, CS => 0 }
+  }
+
+sub loadi {
+       my ($addr, $I) = @_;
+       send_
+         { I => $I, mem_addr => $addr, op => OP_LOADI, CS => 0 }
+}
+
+sub flag_zero { 0 }
+
+sub flag_news { 8 + $_[0] }
+
+sub alu_select_a {
+       0b11110000
+}
+
+sub alu_select_b {
+       0b11001100
+}
+
+sub alu_select_f {
+       0b10101010
+}
+
+sub alu_zero {
+       0
+}
+
+sub alu_xor {
+       0b10010110
+}
+
+sub alu_xnor {
+       0b01101001
+}
+
+sub alu_of_function (&) {
+       my ($fun) = @_;
+       my $alu = 0;
+       for my $i (0 .. 7) {
+               local $a = ($i & 4) >> 2;
+               local $b = ($i & 2) >> 1;
+               local $_ = $i & 1;
+               $alu += ($fun->() ? 1 : 0) << $i;
+       }
+       $alu
+}
+
+sub aluc_add { alu_of_function { ($a + $b + $_) & 2 } }
+sub alus_add { alu_of_function { ($a + $b + $_) & 1 } }
+
+sub aluc_addAF { alu_of_function { ($a + $_) & 2 } }
+sub alus_addAF { alu_of_function { ($a + $_) & 1 } }
+
+sub alu_or { alu_of_function { $a | $b | $_ } }
+
+sub alu2 {
+       my ($aluc, $alus, $addrA, $addrB, $flagr, $flagw, $cond, $inv) = @_;
+       loada $addrA, $flagr, 0, $aluc;
+       loadb $addrB, $cond, $inv, $alus;
+       store $addrA, $flagw, 0, 0;
+}
+
+sub alu3 {
+       my ($aluc, $alus, $addrA, $addrB, $addrC, $flagr, $flagw) = @_;
+       loada $addrA, $flagr, 0, $aluc;
+       loadb $addrB, 0, 1, $alus;
+       store $addrC, $flagw, 0, 0;
+}
+
+sub add {
+       my ($addrA, $addrB, $addrC, $flag_carry) = @_;
+       alu3 aluc_add, alus_add, $addrA, $addrB, $addrC, flag_zero, $flag_carry;
+}
+
+sub addC {
+       my ($addrA, $addrB, $addrC, $flag_carry) = @_;
+       alu3 aluc_add, alus_add, $addrA, $addrB, $addrC, $flag_carry, $flag_carry;
+}
diff --git a/cells.pl b/cells.pl
new file mode 100644 (file)
index 0000000..c8a936a
--- /dev/null
+++ b/cells.pl
@@ -0,0 +1,129 @@
+#!/usr/bin/perl
+use v5.14;
+use warnings;
+use lib '.';
+
+use asm;
+
+sub send_memory_to_news {
+       my ($address) = @_;
+       alu3 alu_select_a, alu_select_a, $address, $address, $address, flag_zero, flag_zero;
+}
+
+sub flag_to_memory {
+       my ($address, $flag) = @_;
+       alu3 alu_zero, alu_select_f, 0, 0, $address, $flag, flag_zero;
+}
+
+my $flag_F = 1;
+
+sub read_write_two_ways {
+       my ($news) = @_;
+       my $memory = $news + 1;
+       send_memory_to_news 0;
+       alu3 alu_zero, alu_select_f, 0, 0, $memory, flag_news($news), flag_zero;
+       send_memory_to_news 0;
+       alu3 aluc_addAF, alus_addAF, $memory, 0, $memory, flag_news($news + 1), $flag_F;
+       flag_to_memory $memory + 1, $flag_F;
+}
+
+sub conway_step {
+       say "CONWAY STEP";
+       # write memory 0 to news
+       # read from news direction 0 into memory 1
+       # write memory 0 to news
+       # read from news direction 1, add to memory 1, write into memory 1 and flag F
+       # write flag F to memory 2
+       read_write_two_ways(0);
+
+       # write memory 0 to news
+       # read from news direction 2 into memory 3
+       # write memory 0 to news
+       # read from news direction 3, add to memory 3, write into memory 3 and flag F
+       # write flag F to memory 4
+       read_write_two_ways(2);
+
+       # write memory 0 to news
+       # read from news direction 4 into memory 5
+       # write memory 0 to news
+       # read from news direction 5, add to memory 5, write into memory 5 and flag F
+       # write flag F to memory 6
+       read_write_two_ways(4);
+
+       # write memory 0 to news
+       # read from news direction 6 into memory 7
+       # write memory 0 to news
+       # read from news direction 7, add to memory 7, write into memory 7 and flag F
+       # write flag F to memory 8
+       read_write_two_ways(6);
+
+       # read from memory 1, add to memory 3, write into memory 1 and flag F
+       add 1, 3, 1, $flag_F;
+       # read from memory 2, add to memory 4 and flag F, write into memory 2 and flag F
+       addC 2, 4, 2, $flag_F;
+       # write flag F to memory 3
+       flag_to_memory 3, $flag_F;
+
+       # read from memory 5, add to memory 7, write into memory 5 and flag F
+       add 5, 7, 5, $flag_F;
+       # read from memory 6, add to memory 8 and flag F, write into memory 6 and flag F
+       addC 6, 8, 6, $flag_F;
+       # write flag F to memory 7
+       flag_to_memory 7, $flag_F;
+
+       # read from memory 1, add to memory 5, write into memory 1 and flag F
+       add 1, 5, 1, $flag_F;
+       # read from memory 2, add to memory 6 and flag F, write into memory 2 and flag F
+       addC 2, 6, 2, $flag_F;
+       # read from memory 3, or with memory 7 and flag F, write into flag F
+       alu3 alu_or, alu_select_a, 3, 7, 3, $flag_F, $flag_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, $flag_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, $flag_F, $flag_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, $flag_F, $flag_F; # also zeroes out flag F
+
+       read_ 0;
+#      say 'Press enter to continue:';
+#      my $nope = <>;
+#      say 'Pressed, continuing';
+       read_ 0;
+#      read_ 1;
+#      read_ 2;
+#      read_ 3;
+#      read_ 4;
+#      read_ 5;
+#      read_ 6;
+
+       sleep 10;
+}
+
+$| = 1;
+
+# start with a blinker
+read_ 0;
+loadi 0, 0x2022;
+#sleep 100;
+
+store 0, flag_zero, 0, 0;
+read_ 0;
+read_ 0;
+sleep 10;
+
+conway_step;
+conway_step;
+conway_step;
+conway_step;
+conway_step;
+conway_step;
diff --git a/chip.v b/chip.v
index 610ad6fc333cdbf3bc9f743da6bc6bee6e254808..ff16cedd5ca796ae4e881ee7f5d643da3b6b8dca 100644 (file)
--- a/chip.v
+++ b/chip.v
@@ -7,22 +7,31 @@
 `define OP_ROUTE 3'd6
 `define OP_RUG   3'd7
 
+`define DIRECTION_N  3'd0
+`define DIRECTION_NE 3'd1
+`define DIRECTION_E  3'd2
+`define DIRECTION_SE 3'd3
+`define DIRECTION_S  3'd4
+`define DIRECTION_SW 3'd5
+`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);
 
    // parity is unimplemented
 
    // OP_LOADA
-   wire [2:0] flagr = I[2:0];
-   wire          bsel = I[3];
-   wire [7:0] aluc = I[11:4];
+   wire [3:0] flagr = I[3:0];
+   wire          bsel = I[4];
+   wire [0:7] aluc = I[12:5];
 
    // OP_LOADB
-   wire [2:0] cond = I[2:0];
-   wire          inv = I[3];
-   wire [7:0] alus = I[11:4];
+   wire [3:0] cond = I[3:0];
+   wire          inv = I[4];
+   wire [0:7] alus = I[12:5];
 
    // OP_STORE
-   wire [2:0] flagw = I[2:0];
+   wire [3:0] flagw = I[3:0];
    wire          edge_ = I[7];
    wire [3:0] cube = I[11:8];
 
@@ -40,101 +49,216 @@ module chip(input clk, input [2:0] op, input [15:0] I, input io_pin, input CS, o
    wire [4:0] reg_ = I[8:4];
 
 
-   reg [15:0] A;
-   reg [15:0] B;
-   reg [15:0] C;
-   reg [15:0] F;
-   reg [15:0] Cond;
-   reg [15:0] R;
-   reg [7:0]  alu_sum;
-   reg [7:0]  alu_carry;
+   reg [15:0] A = 0;
+   reg [15:0] B = 0;
+   reg [15:0] C = 0;
+   reg [15:0] F = 0;
+   reg [15:0] Cond = 0;
+   reg [15:0] R = 0;
+   reg [7:0]  alu_sum = 0;
+   reg [7:0]  alu_carry = 0;
    reg [15:0] cube_in;
    reg                   io;
 
    // these are not really regs
 
-   wire [15:0]  alu_sum_out;
-   wire [15:0]  alu_carry_out;
-
-   wire [2:0]  alu_index [15:0];
-
-assign alu_index[0] = (A[0] << 2) + (B[0] << 1) + F[0];
-assign alu_sum_out[0] = alu_sum[alu_index[0]];
-assign alu_carry_out[0] = alu_carry[alu_index[0]];
-assign alu_index[1] = (A[1] << 2) + (B[1] << 1) + F[1];
-assign alu_sum_out[1] = alu_sum[alu_index[1]];
-assign alu_carry_out[1] = alu_carry[alu_index[1]];
-assign alu_index[2] = (A[2] << 2) + (B[2] << 1) + F[2];
-assign alu_sum_out[2] = alu_sum[alu_index[2]];
-assign alu_carry_out[2] = alu_carry[alu_index[2]];
-assign alu_index[3] = (A[3] << 2) + (B[3] << 1) + F[3];
-assign alu_sum_out[3] = alu_sum[alu_index[3]];
-assign alu_carry_out[3] = alu_carry[alu_index[3]];
-assign alu_index[4] = (A[4] << 2) + (B[4] << 1) + F[4];
-assign alu_sum_out[4] = alu_sum[alu_index[4]];
-assign alu_carry_out[4] = alu_carry[alu_index[4]];
-assign alu_index[5] = (A[5] << 2) + (B[5] << 1) + F[5];
-assign alu_sum_out[5] = alu_sum[alu_index[5]];
-assign alu_carry_out[5] = alu_carry[alu_index[5]];
-assign alu_index[6] = (A[6] << 2) + (B[6] << 1) + F[6];
-assign alu_sum_out[6] = alu_sum[alu_index[6]];
-assign alu_carry_out[6] = alu_carry[alu_index[6]];
-assign alu_index[7] = (A[7] << 2) + (B[7] << 1) + F[7];
-assign alu_sum_out[7] = alu_sum[alu_index[7]];
-assign alu_carry_out[7] = alu_carry[alu_index[7]];
-assign alu_index[8] = (A[8] << 2) + (B[8] << 1) + F[8];
-assign alu_sum_out[8] = alu_sum[alu_index[8]];
-assign alu_carry_out[8] = alu_carry[alu_index[8]];
-assign alu_index[9] = (A[9] << 2) + (B[9] << 1) + F[9];
-assign alu_sum_out[9] = alu_sum[alu_index[9]];
-assign alu_carry_out[9] = alu_carry[alu_index[9]];
-assign alu_index[10] = (A[10] << 2) + (B[10] << 1) + F[10];
-assign alu_sum_out[10] = alu_sum[alu_index[10]];
-assign alu_carry_out[10] = alu_carry[alu_index[10]];
-assign alu_index[11] = (A[11] << 2) + (B[11] << 1) + F[11];
-assign alu_sum_out[11] = alu_sum[alu_index[11]];
-assign alu_carry_out[11] = alu_carry[alu_index[11]];
-assign alu_index[12] = (A[12] << 2) + (B[12] << 1) + F[12];
-assign alu_sum_out[12] = alu_sum[alu_index[12]];
-assign alu_carry_out[12] = alu_carry[alu_index[12]];
-assign alu_index[13] = (A[13] << 2) + (B[13] << 1) + F[13];
-assign alu_sum_out[13] = alu_sum[alu_index[13]];
-assign alu_carry_out[13] = alu_carry[alu_index[13]];
-assign alu_index[14] = (A[14] << 2) + (B[14] << 1) + F[14];
-assign alu_sum_out[14] = alu_sum[alu_index[14]];
-assign alu_carry_out[14] = alu_carry[alu_index[14]];
-assign alu_index[15] = (A[15] << 2) + (B[15] << 1) + F[15];
-assign alu_sum_out[15] = alu_sum[alu_index[15]];
-assign alu_carry_out[15] = alu_carry[alu_index[15]];
-
-   reg [2:0]   flags_addr;
+   reg [15:0]  alu_sum_out;
+   reg [15:0]  alu_carry_out;
+
+   reg [2:0]  alu_index [15:0];
+
+   reg [15:0]  idx;
 
    always @* begin
-         case(op)
-               `OP_LOADA:
-                 flags_addr <= flagr;
-               `OP_LOADB:
-                 flags_addr <= cond;
-               `OP_STORE:
-                 flags_addr <= flagw;
-               default:
-                 flags_addr <= 0;
-         endcase
+         for(idx = 0; idx < 16; idx=idx+1) begin
+                alu_index[idx] = (A[idx] << 2) + (B[idx] << 1) + F[idx];
+                alu_sum_out[idx] <= alu_sum[alu_index[idx]];
+                alu_carry_out[idx] <= alu_carry[alu_index[idx]];
+         end
    end
 
-   wire [15:0] flags_in;
-   reg  [15:0] flags_out;
+   reg [3:0] newstable[0:15][0:7];
+
+   initial begin
+         newstable[0][0] = 12;
+         newstable[0][1] = 13;
+         newstable[0][2] = 1;
+         newstable[0][3] = 5;
+         newstable[0][4] = 4;
+         newstable[0][5] = 7;
+         newstable[0][6] = 3;
+         newstable[0][7] = 15;
+         newstable[1][0] = 13;
+         newstable[1][1] = 14;
+         newstable[1][2] = 2;
+         newstable[1][3] = 6;
+         newstable[1][4] = 5;
+         newstable[1][5] = 4;
+         newstable[1][6] = 0;
+         newstable[1][7] = 12;
+         newstable[2][0] = 14;
+         newstable[2][1] = 15;
+         newstable[2][2] = 3;
+         newstable[2][3] = 7;
+         newstable[2][4] = 6;
+         newstable[2][5] = 5;
+         newstable[2][6] = 1;
+         newstable[2][7] = 13;
+         newstable[3][0] = 15;
+         newstable[3][1] = 12;
+         newstable[3][2] = 0;
+         newstable[3][3] = 4;
+         newstable[3][4] = 7;
+         newstable[3][5] = 6;
+         newstable[3][6] = 2;
+         newstable[3][7] = 14;
+         newstable[4][0] = 0;
+         newstable[4][1] = 1;
+         newstable[4][2] = 5;
+         newstable[4][3] = 9;
+         newstable[4][4] = 8;
+         newstable[4][5] = 11;
+         newstable[4][6] = 7;
+         newstable[4][7] = 3;
+         newstable[5][0] = 1;
+         newstable[5][1] = 2;
+         newstable[5][2] = 6;
+         newstable[5][3] = 10;
+         newstable[5][4] = 9;
+         newstable[5][5] = 8;
+         newstable[5][6] = 4;
+         newstable[5][7] = 0;
+         newstable[6][0] = 2;
+         newstable[6][1] = 3;
+         newstable[6][2] = 7;
+         newstable[6][3] = 11;
+         newstable[6][4] = 10;
+         newstable[6][5] = 9;
+         newstable[6][6] = 5;
+         newstable[6][7] = 1;
+         newstable[7][0] = 3;
+         newstable[7][1] = 0;
+         newstable[7][2] = 4;
+         newstable[7][3] = 8;
+         newstable[7][4] = 11;
+         newstable[7][5] = 10;
+         newstable[7][6] = 6;
+         newstable[7][7] = 2;
+         newstable[8][0] = 4;
+         newstable[8][1] = 5;
+         newstable[8][2] = 9;
+         newstable[8][3] = 13;
+         newstable[8][4] = 12;
+         newstable[8][5] = 15;
+         newstable[8][6] = 11;
+         newstable[8][7] = 7;
+         newstable[9][0] = 5;
+         newstable[9][1] = 6;
+         newstable[9][2] = 10;
+         newstable[9][3] = 14;
+         newstable[9][4] = 13;
+         newstable[9][5] = 12;
+         newstable[9][6] = 8;
+         newstable[9][7] = 4;
+         newstable[10][0] = 6;
+         newstable[10][1] = 7;
+         newstable[10][2] = 11;
+         newstable[10][3] = 15;
+         newstable[10][4] = 14;
+         newstable[10][5] = 13;
+         newstable[10][6] = 9;
+         newstable[10][7] = 5;
+         newstable[11][0] = 7;
+         newstable[11][1] = 4;
+         newstable[11][2] = 8;
+         newstable[11][3] = 12;
+         newstable[11][4] = 15;
+         newstable[11][5] = 14;
+         newstable[11][6] = 10;
+         newstable[11][7] = 6;
+         newstable[12][0] = 8;
+         newstable[12][1] = 9;
+         newstable[12][2] = 13;
+         newstable[12][3] = 1;
+         newstable[12][4] = 0;
+         newstable[12][5] = 3;
+         newstable[12][6] = 15;
+         newstable[12][7] = 11;
+         newstable[13][0] = 9;
+         newstable[13][1] = 10;
+         newstable[13][2] = 14;
+         newstable[13][3] = 2;
+         newstable[13][4] = 1;
+         newstable[13][5] = 0;
+         newstable[13][6] = 12;
+         newstable[13][7] = 8;
+         newstable[14][0] = 10;
+         newstable[14][1] = 11;
+         newstable[14][2] = 15;
+         newstable[14][3] = 3;
+         newstable[14][4] = 2;
+         newstable[14][5] = 1;
+         newstable[14][6] = 13;
+         newstable[14][7] = 9;
+         newstable[15][0] = 11;
+         newstable[15][1] = 8;
+         newstable[15][2] = 12;
+         newstable[15][3] = 0;
+         newstable[15][4] = 3;
+         newstable[15][5] = 2;
+         newstable[15][6] = 14;
+         newstable[15][7] = 10;
+   end // initial begin
+
+   reg [3:0] flags_addr_latch;
+   reg [3:0] flags_addr;
+
+   always @* begin
+         if(flags_addr_latch)
+               flags_addr <= flags_addr_latch;
+         else
+               case(op)
+                 `OP_LOADA:
+                       flags_addr <= flagr;
+                 `OP_LOADB:
+                       flags_addr <= cond;
+                 `OP_STORE:
+                       flags_addr <= flagw;
+                 default:
+                       flags_addr <= 0;
+               endcase
+   end // always @ *
+
+   reg  [15:0] flags_in;
+   wire [15:0] flags_out;
    reg                    flags_write;
 
-   RAM #(.ADDRESS_BITS(3)) flags (.clk(clk), .write(flags_write), .addr(flags_addr), .in(flags_in), .out(flags_out));
+   reg [15:0]  latest_news;
 
-   reg [15:0]  idx;
+   RAM #(.ADDRESS_BITS(3)) flags (.clk(clk), .write(flags_write), .addr(flags_addr[2:0]), .in(flags_in), .out(flags_out));
+
+   reg [15:0]  flag_or_news;
+
+   reg [15:0]  newsidx;
+
+   always @* begin
+         if(flags_addr[3]) begin // read from news
+                for(idx = 0; idx < 16; idx++) begin
+                       newsidx = newstable[idx][flags_addr[2:0]];
+                       flag_or_news[idx] = latest_news[newsidx];
+                end
+         end else begin
+                flag_or_news = flags_out;
+         end
+   end
 
    always @ (posedge clk) begin
          if(mem_write)
                mem_write <= 0;
-         if(flags_write)
-               flags_write <= 0;
+         if(flags_write) begin
+                flags_write <= 0;
+                flags_addr_latch <= 0;
+         end
 
          case (op)
                `OP_NOP: begin end
@@ -142,7 +266,7 @@ assign alu_carry_out[15] = alu_carry[alu_index[15]];
                `OP_LOADA:
                  begin
                         alu_carry <= aluc;
-                        F <= flags_out;
+                        F <= flag_or_news;
                         A <= mem_out;
                         C <= mem_out;
                         io <= io_pin;
@@ -153,19 +277,23 @@ assign alu_carry_out[15] = alu_carry[alu_index[15]];
                `OP_LOADB:
                  begin
                         alu_sum <= alus;
-                        Cond <= inv ? ~flags_out : flags_out;
+                        Cond <= inv ? ~flag_or_news : flag_or_news;
                         B <= mem_out;
                         R <= mem_out;
                  end
 
                `OP_STORE:
                  begin
-                        for(idx=0; idx < 16; idx++)
-                          flags_in[idx] <= Cond[idx] ? alu_carry_out[idx] : flags_out[idx];
-                        flags_write <= 1;
+                        for(idx = 0; idx < 16; idx++) begin
+                               flags_in[idx] = Cond[idx] ? alu_carry_out[idx] : flags_out[idx];
+                               latest_news[idx] <= flags_in[idx];
+                        end
+                        if(flags_addr) begin // we do not write to flag 0
+                               flags_write <= 1;
+                               flags_addr_latch <= flags_addr;
+                        end
                         mem_in <= alu_sum_out;
                         mem_write <= 1;
-                        // lots other stuff
                  end
 
                `OP_READ:
diff --git a/intermediare.pl b/intermediare.pl
new file mode 100644 (file)
index 0000000..91df8ae
--- /dev/null
@@ -0,0 +1,62 @@
+#!/usr/bin/perl
+use v5.14;
+use warnings;
+
+my @initial = (
+       [qw/1 1 1 0/],
+       [qw/0 0 0 0/],
+       [qw/0 0 0 0/],
+       [qw/0 0 0 0/],
+  );
+
+my @diffs = (
+       [-1,  0],
+       [-1,  1],
+       [0 ,  1],
+       [1 ,  1],
+       [1 ,  0],
+       [1 , -1],
+       [0 , -1],
+       [-1, -1]
+);
+
+sub sum_for_diff {
+       my ($diff) = @_;
+       my @result;
+       my ($dx, $dy) = @{$diffs[$diff]};
+       for my $i (0 .. 3) {
+               for my $j (0 .. 3) {
+                       my $ni = ($i + 4 + $dx) % 4;
+                       my $nj = ($j + 4 + $dy) % 4;
+                       $result[$i][$j] = $initial[$ni][$nj];
+               }
+       }
+#      say 'For diff ', $diff, ': ';
+#      say join ' ', @$_ for @result;
+       @result
+}
+
+use Data::Dumper;
+
+my @sum1;
+my @sum2;
+
+for my $x (qw/0 2 4 6/) {
+       @sum1 = sum_for_diff $x;
+       @sum2 = sum_for_diff ($x+1);
+
+       my ($sum1, $sum2, $sumA, $sumB) = (0, 0, 0, 0);
+       my $cnt = 0;
+       for my $i (0 .. 3) {
+               for my $j (0 .. 3) {
+                       my $sum = $sum1[$i][$j] + $sum2[$i][$j];
+                       $sum1 += $sum1[$i][$j] << $cnt;
+                       $sum2 += $sum2[$i][$j] << $cnt;
+                       $sumA += ($sum&1) << $cnt;
+                       $sumB += ($sum&2) << ($cnt - 1);
+                       $cnt++;
+               }
+       }
+
+       printf "%04X + %04X = %016b %016b\n", $sum1, $sum2, $sumA, $sumB;
+}
diff --git a/newstable.pl b/newstable.pl
new file mode 100644 (file)
index 0000000..402de4f
--- /dev/null
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+use v5.14;
+use warnings;
+
+my @diffs = (
+       [-1,  0],
+       [-1,  1],
+       [0 ,  1],
+       [1 ,  1],
+       [1 ,  0],
+       [1 , -1],
+       [0 , -1],
+       [-1, -1]
+);
+
+my @cpus;
+
+my $side = 4; # there are $side * $side CPUs
+
+for my $line (0 .. ($side - 1)) {
+       $cpus[$line] = [ ($line * $side) .. (($line + 1) * $side - 1) ]
+}
+
+for my $cpu (0 .. ($side * $side - 1)) {
+       my $x = $cpu / $side;
+       my $y = $cpu % $side;
+       for my $direction (0 .. 7) {
+               my $nx = ($x + $diffs[$direction][0] + $side) % $side;
+               my $ny = ($y + $diffs[$direction][1] + $side) % $side;
+               say "newstable[$cpu][$direction] = ", $cpus[$nx][$ny], ';';
+       }
+}
diff --git a/ram.v b/ram.v
index 372067543aa9f8de99ede34f79bd53d4962872ac..acd11eeb1613e592e4058f5366cc09d25ccece71 100644 (file)
--- a/ram.v
+++ b/ram.v
@@ -3,6 +3,12 @@ module RAM #(parameter ADDRESS_BITS = 4)
 
     reg [15:0] memory [0:2**ADDRESS_BITS-1];
 
+   reg [ADDRESS_BITS:0] idx;
+   initial begin
+         for(idx = 0; idx < 2**ADDRESS_BITS; idx=idx+1)
+               memory[idx] <= 0;
+   end
+
     always @ (negedge clk) begin
         if (write)
                  memory[addr] <= in;
index 728fee48e28b59c6264d3d950ba6d5c6e7b14a77..f9082347b93abe6ee5236be4380a63e5b3e5b6ff 100644 (file)
@@ -1,16 +1,40 @@
+`include "pll.v"
 `include "ram.v"
 `include "chip.v"
 `include "uart.v"
 
+`ifdef SIM
+ `define UART_DIVIDE 1
+`else
+ `define UART_DIVIDE 1
+ // s/192/3/ for 19200 baud uart
+`endif
+
 module toplevel (input CLKin, output [4:0] led, output uart_tx, input uart_rx);
-   wire clk = CLKin;
+   wire clk;
+   wire clk_tmp;
+
+   //pll pll (.clock_in(CLKin), .clock_out(clk));
+
+   reg [20:0] counter = 0;
+
+   reg                   clk = 0;
+
+   always @ (posedge CLKin) begin
+         if(counter == 5000) begin
+                counter <= 0;
+                clk <= 1 - clk;
+         end
+         else
+               counter <= counter + 1;
+   end
 
    wire [11:0] mem_addr;
    wire [15:0] mem_in;
    wire [15:0] mem_out;
    wire           mem_write;
 
-   RAM #(.ADDRESS_BITS(12)) ram (.clk(clk), .write(mem_write), .addr(mem_addr), .in(mem_in), .out(mem_out));
+   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;
@@ -22,49 +46,73 @@ module toplevel (input CLKin, output [4:0] led, output uart_tx, input uart_rx);
 
    reg [2:0]   op = 0;
 
-   assign led = uart_ptr;
+   reg [2:0]   last_op = 0;
+
+   reg [15:0]  I;
+   reg                    CS;
 
    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));
 
    wire           received;
    wire [7:0]  rx_byte;
    reg                    transmit = 0;
-   reg  [7:0]  tx_byte;
+   reg  [7:0]  tx_byte = 0;
+   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));
 
-   uart uart (.clk(clk), .rx(uart_rx), .tx(uart_tx), .received(received), .transmit(transmit), .tx_byte(tx_byte), .rx_byte(rx_byte));
+   assign led[0] = is_transmitting;
+   assign led[4] = received;
+//   assign led[3:1] = last_op;
 
-   reg [15:0]  rom_I [0:5];
-   reg [7:0]  rom_mem_addr [0:5];
-   reg [2:0]  rom_op [0:5];
-   reg                   rom_CS [0:5];
+   reg                    did_it = 0;
+   assign led[2] = did_it;
 
    reg [2:0]   state = 0;
 
+//   assign led[4:2] = state;
+
    always @ (posedge clk) begin
-         if (received) begin
+         if (state == 0 && received) begin
                 from_uart[uart_ptr] <= rx_byte;
                 uart_ptr <= uart_ptr + 1;
          end
 
-         if (uart_ptr == 4) begin
+         if (state == 0 && uart_ptr == 4) begin
                 op <= op_from_uart;
+                last_op <= op_from_uart;
                 uart_ptr <= 0;
+                did_it <= 1;
                 state <= 1;
          end
 
-         if (state == 1) begin
-                transmit <= 1;
-                tx_byte <= mem_in;
+         if (state == 1 && op != `OP_READ) begin
+                op <= 0;
+                state <= 0;
+         end
+
+         if (state == 1 && op == `OP_READ) begin
+                op <= 0;
                 state <= 2;
+                transmit <= 1;
+                tx_byte <= mem_out[7:0];
          end
 
-         if (state == 2) begin
+         if (state == 2 && transmit) begin
                 transmit <= 0;
-                state <= 0;
          end
 
-         if (op != 0) begin
-                op <= 0;
+         if (state == 2 && !transmit && !is_transmitting) begin
+                state <= 3;
+                transmit <= 1;
+                tx_byte <= mem_out[15:8];
+         end
+
+         if (state == 3) begin
+                transmit <= 0;
+                state <= 0;
          end
    end
 endmodule
index 10f21eca9ecd507c127ebf4655dc12afc7beca53..f82bfb456f6efde9e1f09e2f3d34d45b4e070ef6 100755 (executable)
@@ -1,3 +1,3 @@
-read_verilog -sv -DSIM lisp_processor.v
+read_verilog -sv -DSIM toplevel.v
 prep -top cpu -nordff
 sim -clock clk -vcd test.vcd -n 3000
This page took 0.027364 seconds and 4 git commands to generate.