Skip to content

Commit dc58d8d

Browse files
committed
ready for first release
- fixed Arduino compiler - more documentation - tested SUM mode on 3 Tiles (physical PCB)
1 parent c643f77 commit dc58d8d

8 files changed

+86
-9
lines changed

README.md

+17-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# Discrete 7400 logic based FPGA
2-
A custom, modular FPGA architecture simulated in VHDL (GHDL), realized with discrete 7400-logic ICs and layouted on PCB with KiCAD.
2+
A custom, modular FPGA architecture simulated in VHDL (GHDL), realized with discrete 7400-logic ICs, layouted on PCB with KiCAD and programmed through an abstraction layer via Arduino.
33

44
---
55

6-
![doc/img/architecture-tile.png](doc/img/architecture-tile.png)
6+
![doc/img/fpga-arduino-1.jpg](doc/img/fpga-arduino-1.jpg)
77

8-
Read more on my blog: [mnemocron.github.io](https://mnemocron.github.io/2023-12-08-DIY-FPGA-diary-1/)
8+
Read the full thorugh process and many explanations on my blog:
9+
[mnemocron.github.io](https://mnemocron.github.io/2023-12-08-DIY-FPGA-diary-0/)
910

1011
## Motivation
1112

@@ -15,8 +16,12 @@ Ever since building Ben Eaters [8 bit CPU](https://eater.net/8bit) myself, I wan
1516
The 8 bit CPU is arguably the worst CPU ever built - but it is a fantastic educational example.
1617
And that is the case for the **4 bit FPGA**. It is a purely educational side project that boosted my knowledge about FPGA architecture, VHDL design and verification. Without further ado, here it is.
1718

19+
![doc/img/architecture-tile.png](doc/img/architecture-tile.png)
20+
1821
## Build Process
1922

23+
The actual part list is WIP. Expected material cost are approximately 50 USD per assembled tile (4:4 bit LUT with interconnect).
24+
2025
![doc/img/concept-to-pcb.png](doc/img/concept-to-pcb.png)
2126

2227
---
@@ -32,9 +37,15 @@ Head straight to the `./vhdl/test` directory to see examples with the full FPGA
3237
- `./architecture` contains conceptual draw.io block diagrams
3338
- `./doc` contains images, notes and tools that may be helpful
3439
- `./ihdl` (WIP) contains ideas and concepts for a "compiler"
35-
- `./kicad` contains schematics and PCB files for KiCAD 7.0
36-
- `./sketch` contains Arduino code for testing of assembled PCB hardware
37-
- `./vhdl` contains models for 74xx ICs and the full FPGA architecture
40+
- `./kicad` contains **schematics and PCB files** for KiCAD 7.0
41+
- `./sketch` contains Arduino code for testing of assembled PCB hardware and **abstraction layer in C**
42+
- `./vhdl` contains models for 74xx ICs and the **full FPGA architecture for simulation**
43+
44+
---
45+
46+
## "Assemble" code to map onto the FPGA in Arduino
47+
48+
![doc/img/compiler-design.png](doc/img/compiler-design.png)
3849

3950
---
4051

doc/img/compiler-design.png

28 KB
Loading

doc/img/fpga-arduino-1.jpg

388 KB
Loading

doc/lut_truth_table.xlsx

-33 Bytes
Binary file not shown.

sketch/diyfpga-compile/diyfpga-compile.ino

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#define CLOCK_PIN 8
2323
#define RST_PIN 9
2424

25-
#define CLOCK_HALF_PERIOD 250
25+
#define CLOCK_HALF_PERIOD 50
2626

2727
FILE f_out;
2828
int sput(char c, __attribute__((unused)) FILE* f) {return !Serial.write(c);}

sketch/diyfpga-compile/diyfpga.c

+1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ int create_bitstream(fpga_t* fpga){
143143
// CLB
144144
clb_t* clb = &slc->clb;
145145
SET_CLB_LUT_BITSTREAM(slc);
146+
SET_CLB_INMUX_BITSTREAM(slc);
146147
for(int i=0; i<4; i++){
147148
if(clb->reg[i])
148149
SET_BIT_IN_BITSTREAM(slc, 15-i);

sketch/diyfpga-compile/diyfpga_user.c

+66-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ void diyfpga_setup(){
4848
myfpga.slice[0][0].cbh.sel[1] = BUS_2;
4949
myfpga.slice[0][0].cbh.sel[2] = BUS_1;
5050
myfpga.slice[0][0].cbh.sel[3] = BUS_0;
51-
51+
52+
/*
5253
myfpga.slice[0][1].sw.north[0] = true;
5354
myfpga.slice[0][1].sw.north[1] = true;
5455
myfpga.slice[0][1].sw.north[2] = true;
@@ -77,6 +78,70 @@ void diyfpga_setup(){
7778
myfpga.slice[0][1].sw.north[5] = true;
7879
myfpga.slice[0][1].sw.south[4] = true;
7980
myfpga.slice[0][1].sw.south[5] = true;
81+
*/
82+
83+
myfpga.slice[0][1].sw.north[0] = true;
84+
myfpga.slice[0][1].sw.north[1] = true;
85+
myfpga.slice[0][1].sw.north[2] = true;
86+
myfpga.slice[0][1].sw.north[3] = true;
87+
myfpga.slice[0][1].sw.west[0] = true;
88+
myfpga.slice[0][1].sw.west[1] = true;
89+
myfpga.slice[0][1].sw.west[2] = true;
90+
myfpga.slice[0][1].sw.west[3] = true;
91+
myfpga.slice[0][1].sw.xp[0] = true;
92+
myfpga.slice[0][1].sw.xp[1] = true;
93+
myfpga.slice[0][1].sw.xp[2] = true;
94+
myfpga.slice[0][1].sw.xp[3] = true;
95+
myfpga.slice[0][1].clb.reg[0] = true;
96+
myfpga.slice[0][1].clb.reg[1] = true;
97+
myfpga.slice[0][1].clb.reg[2] = true;
98+
myfpga.slice[0][1].clb.reg[3] = true;
99+
myfpga.slice[0][1].clb.sum = true;
100+
myfpga.slice[0][0].clb.clk_sel = 0;
101+
myfpga.slice[0][0].clb.clk_en = false;
102+
myfpga.slice[0][1].clb.in_mux[0] = SUM_INPUT;
103+
myfpga.slice[0][1].clb.in_mux[1] = SUM_INPUT;
104+
myfpga.slice[0][1].clb.in_mux[2] = SUM_INPUT;
105+
myfpga.slice[0][1].clb.in_mux[3] = SUM_INPUT;
106+
myfpga.slice[0][1].clb.lut[0] = 0x6;
107+
myfpga.slice[0][1].clb.lut[1] = 0x6;
108+
myfpga.slice[0][1].clb.lut[2] = 0x6;
109+
myfpga.slice[0][1].clb.lut[3] = 0x6;
110+
myfpga.slice[0][1].cbv.bus[0] = true;
111+
myfpga.slice[0][1].cbv.bus[1] = true;
112+
myfpga.slice[0][1].cbv.bus[2] = true;
113+
myfpga.slice[0][1].cbv.bus[3] = true;
114+
115+
myfpga.slice[0][2].clb.reg[0] = true;
116+
myfpga.slice[0][2].clb.reg[1] = true;
117+
myfpga.slice[0][2].clb.reg[2] = true;
118+
myfpga.slice[0][2].clb.reg[3] = true;
119+
myfpga.slice[0][2].clb.clk_sel = 0;
120+
myfpga.slice[0][2].clb.clk_en = false;
121+
myfpga.slice[0][2].clb.sum = false;
122+
123+
myfpga.slice[0][2].clb.lut[0] = 0x1; // 0x00FF;
124+
myfpga.slice[0][2].clb.lut[1] = 0x0; // 0x0FF0;
125+
myfpga.slice[0][2].clb.lut[2] = 0x0; // 0x3CCC;
126+
myfpga.slice[0][2].clb.lut[3] = 0x0; // 0x6AAA;
127+
128+
myfpga.slice[0][2].cbv.bus[0] = true;
129+
myfpga.slice[0][2].cbv.bus[1] = true;
130+
myfpga.slice[0][2].cbv.bus[2] = true;
131+
myfpga.slice[0][2].cbv.bus[3] = true;
132+
133+
myfpga.slice[0][2].sw.xp[0] = true;
134+
myfpga.slice[0][2].sw.xp[1] = true;
135+
myfpga.slice[0][2].sw.xp[2] = true;
136+
myfpga.slice[0][2].sw.xp[3] = true;
137+
myfpga.slice[0][2].sw.south[0] = true;
138+
myfpga.slice[0][2].sw.south[1] = true;
139+
myfpga.slice[0][2].sw.south[2] = true;
140+
myfpga.slice[0][2].sw.south[3] = true;
141+
myfpga.slice[0][2].sw.west[0] = true;
142+
myfpga.slice[0][2].sw.west[1] = true;
143+
myfpga.slice[0][2].sw.west[2] = true;
144+
myfpga.slice[0][2].sw.west[3] = true;
80145

81146
}
82147

sketch/diyfpga-compile/diyfpga_user.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
// How many slices does the FPGA have? (2D matrix)
1414
#define N_SLICE_X (1)
15-
#define N_SLICE_Y (2)
15+
#define N_SLICE_Y (3)
1616

1717
#define ENABLE_PRINT_MESSAGES false
1818

0 commit comments

Comments
 (0)