From: Marius Gavrilescu Date: Sat, 2 Mar 2019 19:42:50 +0000 (+0000) Subject: worker/master split X-Git-Url: http://git.ieval.ro/?a=commitdiff_plain;h=3b542afc856d736dfd2ff0eed081f647de07af4c;p=clump.git worker/master split --- diff --git a/asm.pm b/asm.pm index d07004e..492bfcc 100644 --- a/asm.pm +++ b/asm.pm @@ -102,6 +102,7 @@ sub loadi { } sub flag_zero { 0 } +sub flag_temp { 7 } sub flag_news { 8 + $_[0] } @@ -172,3 +173,57 @@ sub addC { my ($addrA, $addrB, $addrC, $flag_carry) = @_; alu3 aluc_add, alus_add, $addrA, $addrB, $addrC, $flag_carry, $flag_carry; } + +# news_gen face partea de mijloc +# news_[mf][mf] face primul alu3, apeleaza news_gen, apoi face ultimul alu3 +sub news_generic { + my ($nX, $nY, $dest) = @_; + my %dest = %$dest; + while ($nX || $nY) { + my $direction; + if ($nX && $nY) { + $nX--; + $nY--; + $direction = 7; + } elsif ($nX) { + $nX--; + $direction = 0; + } else { + $nY--; + $direction = 6; + } + if ($nX || $nY) { # not the last go + alu3 alu_select_f, alu_select_a, 0, 0, 0, flag_news($direction), flag_zero + } elsif (exists $dest{address}) { + alu3 alu_select_f, alu_select_f, 0, 0, $dest{address}, flag_news($direction), flag_zero + } elsif (exists $dest{flag}) { + alu3 alu_select_f, alu_select_a, 0, 0, 0, flag_news($direction), $dest{flag} + } else { + die "No destination address nor flag given to [news_generic]\n" + } + } +} + +sub news_mm { + my ($addrIN, $addrOUT, $nX, $nY) = @_; + alu3 alu_select_a, alu_select_a, $addrIN, 0, $addrIN, flag_zero, flag_zero; + news_generic $nX, $nY, {address => $addrOUT}; +} + +sub news_mf { + my ($addrIN, $flagOUT, $nX, $nY) = @_; + alu3 alu_select_a, alu_select_a, $addrIN, 0, $addrIN, flag_zero, flag_zero; + news_generic $nX, $nY, {flag => $flagOUT}; +} + +sub news_fm { + my ($flagIN, $addrOUT, $nX, $nY) = @_; + alu3 alu_select_f, alu_select_a, 0, 0, 0, $flagIN, flag_zero; + news_generic $nX, $nY, {address => $addrOUT}; +} + +sub news_ff { + my ($flagIN, $flagOUT, $nX, $nY) = @_; + alu3 alu_select_f, alu_select_a, 0, 0, 0, $flagIN, flag_zero; + news_generic $nX, $nY, {flag => $flagOUT}; +} diff --git a/chip.v b/chip.v index ff16ced..b29fde6 100644 --- a/chip.v +++ b/chip.v @@ -1,3 +1,5 @@ +`include "news.v" + `define OP_NOP 3'd0 `define OP_LOADA 3'd1 `define OP_LOADB 3'd2 @@ -16,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); +module chip(input clk, input [2:0] op, input [15:0] I, input io_pin, input CS, output reg [63:0] mem_in, input [63:0] mem_out, output reg mem_write); // parity is unimplemented @@ -49,167 +51,34 @@ 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 = 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 [63:0] A = 0; + reg [63:0] B = 0; + reg [63:0] C = 0; + reg [63:0] F = 0; + reg [63:0] Cond = 0; + reg [63:0] R = 0; reg [7:0] alu_sum = 0; reg [7:0] alu_carry = 0; - reg [15:0] cube_in; + reg [63:0] cube_in; reg io; // these are not really regs - reg [15:0] alu_sum_out; - reg [15:0] alu_carry_out; + reg [63:0] alu_sum_out; + reg [63:0] alu_carry_out; - reg [2:0] alu_index [15:0]; + reg [2:0] alu_index [63:0]; reg [15:0] idx; always @* begin - for(idx = 0; idx < 16; idx=idx+1) begin + for(idx = 0; idx < 64; 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 - 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; @@ -229,28 +98,20 @@ module chip(input clk, input [2:0] op, input [15:0] I, input io_pin, input CS, o endcase end // always @ * - reg [15:0] flags_in; - wire [15:0] flags_out; + reg [63:0] flags_in; + wire [63:0] flags_out; reg flags_write; - reg [15:0] latest_news; + reg [63:0] latest_news; 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 [63:0] flag_or_news; + reg [63:0] news_out; - reg [15:0] newsidx; + news newspaper (.news_in(latest_news), .direction(flags_addr[1:0]), .news_out(news_out)); - 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 + assign flag_or_news = flags_addr[3] ? news_out : flags_out; always @ (posedge clk) begin if(mem_write) @@ -284,7 +145,7 @@ module chip(input clk, input [2:0] op, input [15:0] I, input io_pin, input CS, o `OP_STORE: begin - for(idx = 0; idx < 16; idx++) begin + for(idx = 0; idx < 64; idx++) begin flags_in[idx] = Cond[idx] ? alu_carry_out[idx] : flags_out[idx]; latest_news[idx] <= flags_in[idx]; end diff --git a/master.v b/master.v new file mode 100644 index 0000000..0057388 --- /dev/null +++ b/master.v @@ -0,0 +1,80 @@ +`include "master_rom.v" + +`ifdef SIM + `define UART_DIVIDE 1 +`else + `define UART_DIVIDE 1 + // s/192/3/ for 19200 baud uart +`endif + +module master(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)); + + 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 + + reg [4:0] program_counter = 0; + wire [63:0] rom_output; + + 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 + + reg [5:0] state = `STATE_SEND; + reg [5:0] uart_ptr = 0; + + wire received; + wire [7:0] rx_byte; + reg transmit = 0; + 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)); + + always @(posedge clk) begin + case(state) + `STATE_SEND: begin + if(transmit) begin + transmit <= 0; + end else if(uart_ptr == 4) begin + program_counter <= program_counter + 1; + uart_ptr <= 0; + state <= `STATE_WAIT_PROPAGATE; + end else if(!is_transmitting && ready_in) begin + tx_byte <= rom_output[uart_ptr * 8 +: 8]; + transmit <= 1; + uart_ptr <= uart_ptr + 1; + end + end + + `STATE_WAIT_PROPAGATE: begin + if(received) begin + state <= `STATE_SEND; + end + end + + `STATE_WAIT_NEWS: begin + + end + endcase + end + +endmodule diff --git a/master_rom.v b/master_rom.v new file mode 100644 index 0000000..f950628 --- /dev/null +++ b/master_rom.v @@ -0,0 +1,26 @@ +// 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 [63:0] data); + always @ (posedge clk) begin + case(addr) + 4'd0: data <= 8'b0001_0110; // LDI 6 + 4'd1: data <= 8'b0110_0010; // JP 9 + 4'd2: data <= 8'b0010_0001; // ADD 1 + 4'd3: data <= 8'b1001_0000; // WRITE + 4'd4: data <= 8'b0110_0010; // JP 2 + 4'd5: data <= 8'b0000_0000; + 4'd6: data <= 8'b0001_0001; // LDI 1 + 4'd7: data <= 8'b1000_0000; // READ + 4'd8: data <= 8'b0110_0111; // JP 7 + 4'd9: data <= 8'b1110_0000; // LDQ + 4'd10: data <= 8'b0001_1100; // LDI 12 + 4'd11: data <= 8'b1010_0000; // CONS + 4'd12: data <= 8'b1100_0000; // RDQ + 4'd13: data <= 8'b1101_0000; // CDR + 4'd14: data <= 8'b1100_0000; // RDQ + 4'd15: data <= 8'b0000_0000; + default: data <= 8'bxxxx_xxxx; + endcase + end +endmodule diff --git a/news.v b/news.v new file mode 100644 index 0000000..d2e1def --- /dev/null +++ b/news.v @@ -0,0 +1,11 @@ +module news(input clk, input [63:0] news_in, input [1:0] direction, output [63:0] news_out); + always @(posedge clk) begin + case (direction) + 0: news_out = {news_in[56:63], news_in[0:55]}; + 1: news_out = {news_in[ 1], news_in[ 2], news_in[ 3], news_in[ 4], news_in[ 5], news_in[ 6], news_in[ 7], news_in[ 0], news_in[ 9], news_in[10], news_in[11], news_in[12], news_in[13], news_in[14], news_in[15], news_in[ 8], news_in[17], news_in[18], news_in[19], news_in[20], news_in[21], news_in[22], news_in[23], news_in[16], news_in[25], news_in[26], news_in[27], news_in[28], news_in[29], news_in[30], news_in[31], news_in[24], news_in[33], news_in[34], news_in[35], news_in[36], news_in[37], news_in[38], news_in[39], news_in[32], news_in[41], news_in[42], news_in[43], news_in[44], news_in[45], news_in[46], news_in[47], news_in[40], news_in[49], news_in[50], news_in[51], news_in[52], news_in[53], news_in[54], news_in[55], news_in[48], news_in[57], news_in[58], news_in[59], news_in[60], news_in[61], news_in[62], news_in[63], news_in[56]}; + 2: news_out = {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[16], news_in[17], news_in[18], news_in[19], news_in[20], news_in[21], news_in[22], news_in[23], news_in[24], news_in[25], news_in[26], news_in[27], news_in[28], news_in[29], news_in[30], news_in[31], news_in[32], news_in[33], news_in[34], news_in[35], news_in[36], news_in[37], news_in[38], news_in[39], news_in[40], news_in[41], news_in[42], news_in[43], news_in[44], news_in[45], news_in[46], news_in[47], news_in[48], news_in[49], news_in[50], news_in[51], news_in[52], news_in[53], news_in[54], news_in[55], news_in[56], news_in[57], news_in[58], news_in[59], news_in[60], news_in[61], news_in[62], news_in[63], news_in[ 0], news_in[ 1], news_in[ 2], news_in[ 3], news_in[ 4], news_in[ 5], news_in[ 6], news_in[ 7]}; + 3: news_out = {news_in[ 7], news_in[ 0], news_in[ 1], news_in[ 2], news_in[ 3], news_in[ 4], news_in[ 5], news_in[ 6], news_in[15], news_in[ 8], news_in[ 9], news_in[10], news_in[11], news_in[12], news_in[13], news_in[14], news_in[23], news_in[16], news_in[17], news_in[18], news_in[19], news_in[20], news_in[21], news_in[22], news_in[31], news_in[24], news_in[25], news_in[26], news_in[27], news_in[28], news_in[29], news_in[30], news_in[39], news_in[32], news_in[33], news_in[34], news_in[35], news_in[36], news_in[37], news_in[38], news_in[47], news_in[40], news_in[41], news_in[42], news_in[43], news_in[44], news_in[45], news_in[46], news_in[55], news_in[48], news_in[49], news_in[50], news_in[51], news_in[52], news_in[53], news_in[54], news_in[63], news_in[56], news_in[57], news_in[58], news_in[59], news_in[60], news_in[61], news_in[62]}; + endcase + + end +endmodule diff --git a/newstable.pl b/newstable.pl index 402de4f..233d317 100644 --- a/newstable.pl +++ b/newstable.pl @@ -4,18 +4,20 @@ use warnings; my @diffs = ( [-1, 0], - [-1, 1], +# [-1, 1], [0 , 1], - [1 , 1], +# [1 , 1], [1 , 0], - [1 , -1], +# [1 , -1], [0 , -1], - [-1, -1] +# [-1, -1] ); my @cpus; -my $side = 4; # there are $side * $side CPUs +my @newstable; + +my $side = 8; # there are $side * $side CPUs for my $line (0 .. ($side - 1)) { $cpus[$line] = [ ($line * $side) .. (($line + 1) * $side - 1) ] @@ -24,9 +26,18 @@ for my $line (0 .. ($side - 1)) { for my $cpu (0 .. ($side * $side - 1)) { my $x = $cpu / $side; my $y = $cpu % $side; - for my $direction (0 .. 7) { + for my $direction (0 .. $#diffs) { my $nx = ($x + $diffs[$direction][0] + $side) % $side; my $ny = ($y + $diffs[$direction][1] + $side) % $side; - say "newstable[$cpu][$direction] = ", $cpus[$nx][$ny], ';'; + $newstable[$cpu][$direction] = $cpus[$nx][$ny]; + } +} + +for my $direction (0 .. $#diffs) { + print "$direction: flag_or_news = {"; + printf 'latest_news[%2d]', $newstable[0][$direction]; + for my $cpu (1 .. ($side * $side - 1)) { + printf ', latest_news[%2d]', $newstable[$cpu][$direction]; } + say '};' } diff --git a/ram.v b/ram.v index acd11ee..28e0f06 100644 --- a/ram.v +++ b/ram.v @@ -1,7 +1,7 @@ module RAM #(parameter ADDRESS_BITS = 4) -(input clk, input write, input[ADDRESS_BITS-1:0] addr, input [15:0] in, output reg [15:0] out); +(input clk, input write, input[ADDRESS_BITS-1:0] addr, input [63:0] in, output reg [63:0] out); - reg [15:0] memory [0:2**ADDRESS_BITS-1]; + reg [63:0] memory [0:2**ADDRESS_BITS-1]; reg [ADDRESS_BITS:0] idx; initial begin diff --git a/toplevel.v b/toplevel.v index f908234..5939ffe 100644 --- a/toplevel.v +++ b/toplevel.v @@ -1,118 +1,19 @@ -`include "pll.v" -`include "ram.v" -`include "chip.v" -`include "uart.v" +`include "master.v" +`include "worker.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); + wire worker_tx; + wire worker_rx; -module toplevel (input CLKin, output [4:0] led, output uart_tx, input uart_rx); - wire clk; - wire clk_tmp; + wire worker_ready; + wire master_ready; - //pll pll (.clock_in(CLKin), .clock_out(clk)); + wire [4:0] worker_led; + wire [4:0] master_led; - reg [20:0] counter = 0; + worker worker (.CLKin(CLKin), .led(worker_led), .uart_tx(worker_tx), .uart_rx(worker_rx), .ready_out(worker_ready), .ready_in(master_ready)); - reg clk = 0; + master master (.CLKin(CLKin), .led(master_led), .uart_tx(worker_rx), .uart_rx(worker_tx), .ready_out(master_ready), .ready_in(worker_ready)); - 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(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 CS = from_uart[3][3]; - - reg [2:0] op = 0; - - 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 = 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)); - - assign led[0] = is_transmitting; - assign led[4] = received; -// assign led[3:1] = last_op; - - reg did_it = 0; - assign led[2] = did_it; - - reg [2:0] state = 0; - -// assign led[4:2] = state; - - always @ (posedge clk) begin - if (state == 0 && received) begin - from_uart[uart_ptr] <= rx_byte; - uart_ptr <= uart_ptr + 1; - end - - 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 && 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 && transmit) begin - transmit <= 0; - end - - 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 + assign led = worker_led | master_led; endmodule diff --git a/worker.v b/worker.v new file mode 100644 index 0000000..7a5a909 --- /dev/null +++ b/worker.v @@ -0,0 +1,160 @@ +`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 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)); + + 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 [63:0] mem_in; + wire [63:0] mem_out; + wire mem_write; + + 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 CS = from_uart[3][3]; + + reg [2:0] op = 0; + + 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 = 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)); + + assign led[0] = is_transmitting; + assign led[4] = received; +// assign led[3:1] = last_op; + + assign led[2] = |mem_out; // so that mem_out is used + + // 0 is idle +`define STATE_IDLE 0 +`define STATE_PROPAGATE 1 +`define STATE_EXECUTE 2 +`define STATE_ROUTE 3 + + reg [5:0] state = 0; + +// assign led[4:2] = state; + + always @ (posedge clk) begin + case(state) + `STATE_IDLE: begin + if(uart_ptr == 4) begin + last_op <= op_from_uart; + uart_ptr <= 0; + state <= `STATE_PROPAGATE; + ready_out <= 0; + end + else if (received) begin + from_uart[uart_ptr] <= rx_byte; + uart_ptr <= uart_ptr + 1; + end else + ready_out <= 1; + end + + `STATE_PROPAGATE: begin + if(transmit) + transmit <= 0; + else if(uart_ptr == 4) begin + uart_ptr <= 0; + if(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]; + transmit <= 1; + uart_ptr <= uart_ptr + 1; + end + end + + `STATE_EXECUTE: begin + op <= 0; + state <= `STATE_IDLE; + end + + `STATE_ROUTE: begin + state <= `STATE_IDLE; // for now + end + endcase + + /* + + 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 && transmit) begin + transmit <= 0; + end + + 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 + + wire ready = (state == 0 && !is_receiving); + + assign ready_out = ready_in & ready; + +endmodule