Adaptation of the https://github.com/progranism/Open-Source-FPGA-Bitcoin-Miner for the Lattice ECP5 evaluation board (LFE5UM5G-85F-8BG381). It has been tested on the actual board with the pc-comm
script found in the helpers directory
. Tests are provided for most of the modules.
There's a great video on youtube explaining how sha256 works and it can serve as a great reference to this implementation: https://www.youtube.com/watch?v=f9EbD6iY9zI
The implementation pipelines the 64 stages of sha256 calculation. If the calculations are fully unrolled, you will get one hash per clock cycle (ofcourse, you will get the first hash after 64 clock cycles, and one per cycle after that). Since bitcoin uses double sha256 hashing, this is done twice. The first part of the bitcoin header is pre-hashed and sent to the FPGA via the MSG_PUSH_JOB command. FPGA modifies the nonce and calculates the hash of the second part. The resulting hash is then hashed again. If the target is reached, we've successfully mined the block.
Test with make test-top
, make test-uart
, make test-miner
. Tests for the top module and the miner module will mine the genesis block.
Build with make
.
Flash the ECP5evn with make program
.
Compile C code in helpers
directory with gcc pc-comm.c -o pc-comm
and run with ./pc-comm
to observe serial packets.
Send packets to FPGA with bash command:
- Get info:
echo -en '\x08\x00\x00\x00\xf9\xea\x98\x0a' > /dev/ttyUSB2
- Ping:
echo -en '\x00' > /dev/ttyUSB2
- Send genesis block mine:
echo -en '\x3C\x00\x00\x02\xFF\xFF\xFF\xFF\x7B\x2B\xAC\x1D\x4A\x5E\x1E\x4B\x49\x5F\xAB\x29\x1d\x00\xFF\xFF\x33\x9A\x90\xBC\xF0\xBF\x58\x63\x7D\xAC\xCC\x90\xA8\xCA\x59\x1E\xE9\xD8\xC8\xC3\xC8\x03\x01\x4F\x36\x87\xB1\x96\x1B\xF9\x19\x47\x77\x15\x4f\x81' > /dev/ttyUSB2
Both should return either pong or the info you can find harcoded in the uart_comm
file:
- Pong:
0x01
- Get info response:
0x10 00 00 00 de ad be ef 13 37 0d 13 00 00 00 00
- Genesis block send response:
0x01
- acknowledge,08 00 00 03 1d ac 2b 7c
nonce
read -vlog2k src/*.v
proc;
- Block headers are currently byte reversed in blocks of 4 bytes for the miner to work correctly. I suspect this is due to the pool's way of calculating midstate. We should be able to circumvent this when calculating our own midstate hashes with minor modifications of the mining code.
- Difficulty should not be hardcoded. It is also incorrect to check for the leading number of zeroes in a hash, when the blocks are byte reversed in blocks of 4 bytes.
- Write the miner "brain" for ESP32/PC
You can modify how unrolled the SHA calculations are with parameter LOOP_LOG2
[0, 5]. The larger the value, the smaller and slower the program.
LOOP_LOG2=3
Info: Logic utilisation before packing:
Info: Total LUT4s: 32001/83640 38%
Info: logic LUTs: 29309/83640 35%
Info: carry LUTs: 2692/83640 3%
Info: RAM LUTs: 0/41820 0%
Info: RAMW LUTs: 0/20910 0%
Info: Total DFFs: 30482/83640 36%
LOOP_LOG2=2
Info: Logic utilisation before packing:
Info: Total LUT4s: 61869/83640 73%
Info: logic LUTs: 57065/83640 68%
Info: carry LUTs: 4804/83640 5%
Info: RAM LUTs: 0/41820 0%
Info: RAMW LUTs: 0/20910 0%
Info: Total DFFs: 55056/83640 65%
LOOP_LOG2=1
and LOOP_LOG2=0
do not fit on the board.
Command to generate it:
make generate-image