compudanzas/src/bouncing_ball_logic.gmo

211 lines
4.2 KiB
Plaintext

# bouncing ball logic
lang=en
may this serve as a reference for non-electronic, human-scale, very-slow implementations of digital circuits that embody a virtual ball bouncing in a screen.
these notes emerged from the work around {poñg}, "a human-scale digital videogame, with logic provided by people".
this is a sub-collection from the {logiteca}.
# 1-dimension
## 4-pixels wide screen
the ball is a pixel that bounces back and forth.
description of the logic in {verilog}:
```
// bouncing ball (pixel) in a 4-pixels screen
// using NOR gates
module onedimensional_bounce( E2, E1, E0, P3, P2, P1, P0, NE2, NE1, NE0 );
input wire E2, E1, E0; // curent state
output wire P3, P2, P1, P0; // pixels
output wire NE2, NE1, NE0; // next state
// inversions
wire nE2, nE1, nE0;
// ors
wire NE0_1, NE0_2, NE1_2;
// input inversions (3 gates)
not g00( nE0, E0);
not g01( nE1, E1);
not g02( nE2, E2);
// NE2
assign NE2 = E1;
// NE1
nor g03( NE1_2, nE2, nE0);
nor g04( NE1, P0, NE1_2);
// NE0
nor g05( NE0_1, nE2, E1, nE0);
nor g06( NE0_2, E2, nE1, nE0);
nor g07( NE0, NE0_1, NE0_2);
// pixels
nor g08( P3, nE1, E0);
nor g09( P2, nE1, nE0);
nor g10( P1, E1, nE0);
nor g11( P0, E1, E0); // also "NE1_1"
endmodule
```
### board and cards implementation
compatible with {beans computing}: use two classes of beans to indicate a 1 or a 0.
current state:
```
+----+----+----+
| i2 | i1 | i0 |
+----+----+----+
```
process helpers
```
+----+----+----+----+----+----+
| p5 | p4 | p3 | p2 | p1 | p0 |
+----+----+----+----+----+----+
```
next state and screen:
```
+----+----+----+ +----+----+----+----+
| o6 | o5 | o4 | | o3 | o2 | o1 | o0 |
+----+----+----+ +----+----+----+----+
```
the NOR-based cards for process and output cells:
process helpers:
```
p0: i0
p1: i1
p2: i2
p3: p2, p0
p4: p2, i1, p0
p5: i2, p1, p0
```
next state:
```
o6: p1
o5: o0, p3
o4: p4, p5
```
screen:
```
o3: p1, i0
o2: p1, p0
o1: i1, p0
o0: i1, i0
```
(card p0 would be read: p0 is 1 when i0 is 0, and it's 0 otherwise; card p5 would be read: p5 is 1 when all i2, p1 and p0 are 0, and it's 0 otherwise)
# 2-dimensions
## 8x6 screen
the following description, converted into a gate-level representation, results in the {bouncer-2d prototype}. the notes of how that process happened have to be recovered and documented here.
### high-level verilog code
```
module bouncer2d
#(
parameter PIXELSW = 8,
parameter PIXELSH = 6
)
(
input [$clog2(PIXELSW)-1:0] posx,
input [$clog2(PIXELSH)-1:0] posy,
input dirx,
input diry,
output [$clog2(PIXELSW)-1:0] newposx,
output [$clog2(PIXELSH)-1:0] newposy,
output newdirx,
output newdiry,
output [(PIXELSW*PIXELSH)-1:0] screen
);
bouncer1d #( .NPIXELS( PIXELSW)) bouncex (
.pos( posx ),
.dir( dirx ),
.newpos( newposx ),
.newdir( newdirx )
);
bouncer1d #( .NPIXELS( PIXELSH)) bouncey (
.pos( posy ),
.dir( diry ),
.newpos( newposy ),
.newdir( newdiry )
);
screen_decoder #(.PIXELSW(PIXELSW), .PIXELSH( PIXELSH ))
decoder (
.posx( posx ),
.posy( posy ),
.screen( screen )
);
endmodule // bouncer2d
module screen_decoder
#(
parameter PIXELSW = 8,
parameter PIXELSH = 6
)
(
input [$clog2(PIXELSW)-1:0] posx,
input [$clog2(PIXELSH)-1:0] posy,
output [(PIXELSW*PIXELSH)-1:0] screen
);
// decoder!
genvar c, r;
generate
for(c=0; c<PIXELSW; c = c + 1) begin
for(r=0; r<PIXELSH; r = r + 1) begin
assign screen[c + r*PIXELSW] = (posx==c) && (posy==r);
end
end
endgenerate
// another possibility, less effective while synthesizing
// assign screen = (1<<posx) << (posy*PIXELSW);
endmodule // screen_decoder
module bouncer1d
#( parameter NPIXELS = 8)
(
input [$clog2(NPIXELS)-1:0] pos,
input dir, // 1 inc, 0 dec
output [$clog2(NPIXELS)-1:0] newpos,
output newdir
);
/* //without edge-cases
assign newdir = (dir==1 && pos==(NPIXELS-2)) ? 0 : (dir==0 && pos==1) ? 1 : dir;
assign newpos = (dir==1) ? pos + 1 : pos - 1;
*/
// with edge cases (and less gates when synthesizing!)
assign newdir = (pos==0) ? 1 : (pos>=NPIXELS-1) ? 0 : (dir==1 && pos==NPIXELS-2) || (dir==0 && pos==1) ? ~dir : dir;
assign newpos = (pos==0) ? 1 : (pos>=NPIXELS-1) ? NPIXELS - 2 : (dir==1)? pos + 1 : pos -1;
endmodule
```