Skip to content

Commit

Permalink
A few modifications to udif's patch. Moved testing to a separate test…
Browse files Browse the repository at this point in the history
…bench. Created a testbenches folder with the first testbench in it. Tested udif's patch and it works for all LOOP_LOG2 settings from 0 to 5. Added golden_nonce adjustment code so the mining script no longer has to make the adjustments. Mining script updated with TODOs and removed the golden_nonce adjustments.
  • Loading branch information
fpgaminer committed Jun 1, 2011
1 parent 18cb8d6 commit ada8faf
Show file tree
Hide file tree
Showing 10 changed files with 1,503 additions and 87 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ db
incremental_db
work
quartus_output
PLLJ_PLLSPE_INFO.txt
PLLJ_PLLSPE_INFO.txt
*.cr.mti
vsim.wlf
transcript
16 changes: 11 additions & 5 deletions scripts/mine/mine.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
#
##


## TODO: Probe for Hardware and Device names and allow user to select.
## TODO: Allow user to enter username/password pairs and pool server info.
## TDOO: Save user configurations to a file and load on start.
## TODO: Log JSON-RPC information to a file instead of spitting it into the console, or make it a --verbose option.
## TODO: Long polling.
## TODO: Use the NONC virtual wire to measure hashrate.


package ifneeded TclCurl 7.19.6 [list load TclCurl7196.dll]\n[list source tclcurl.tcl]
package require TclCurl
package require json
Expand Down Expand Up @@ -100,9 +109,6 @@ proc get_work {} {
set target [dict get $json_result target]

write_instance "STAT" [reverseHex $midstate]
#write_instance "TARG" [reverseHex $target]
#write_instance "HSH1" [string range [reverseHex $hash1] 0 63]
#write_instance "DATA" [string range [reverseHex $data] 0 63]
write_instance "DAT2" [string range [reverseHex $data] 64 127]

return $data
Expand Down Expand Up @@ -137,8 +143,8 @@ proc wait_for_golden_ticket {timeout} {
proc submit_work {data nonce} {
puts "Hex nonce: $nonce"
set nonce [expr 0x$nonce]
set nonce [expr {$nonce - 132}]
puts "New nonce: $nonce"
#set nonce [expr {$nonce - 132}] # No longer need to re-adjust nonce, the FPGA takes care of that.
#puts "New nonce: $nonce"
set nonce [format %x $nonce]
puts "New nonce hex: $nonce"

Expand Down
2 changes: 1 addition & 1 deletion scripts/program/program-fpga-board.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ puts "Selected USB device: $hardware_name\n\n\n"


# Now let the user select which SOF to program
set sof_files [glob *.sof ../../projects/*/quartus_output/*.sof]
set sof_files [glob *.sof]
set id 0

foreach sof_file $sof_files {
Expand Down
127 changes: 61 additions & 66 deletions src/fpgaminer_top.v
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,26 @@

module fpgaminer_top (osc_clk);

localparam LOOP_LOG2 = 3;
localparam [5:0]LOOP = (6'd1 << LOOP_LOG2);
// The LOOP_LOG2 parameter determines how unrolled the SHA-256
// calculations are. For example, a setting of 1 will completely
// unroll the calculations, resulting in 128 rounds and a large, fast
// design.
//
// A setting of 2 will result in 64 rounds, with half the size and
// half the speed. 3 will be 32 rounds, with 1/4th the size and speed.
// And so on.
//
// Valid range: [0, 5]
parameter LOOP_LOG2 = 0;

// No need to adjust these parameters
localparam [5:0] LOOP = (6'd1 << LOOP_LOG2);
// The nonce will always be larger at the time we discover a valid
// hash. This is its offset from the nonce that gave rise to the valid
// hash (except when LOOP_LOG2 == 0 or 1, where the offset is 131 or
// 66 respectively).
localparam [31:0] GOLDEN_NONCE_OFFSET = (32'd1 << (7 - LOOP_LOG2)) + 32'd1;

input osc_clk;


Expand All @@ -34,37 +52,31 @@ module fpgaminer_top (osc_clk);
reg [511:0] data = 0;
reg [31:0] nonce = 32'h00000000;


//// PLL
wire hash_clk;
`ifndef SIM
//main_pll pll_blk (osc_clk, hash_clk);
assign hash_clk = osc_clk;
`endif


//// Simulation Timer
`ifdef SIM
reg gen_clk = 0;
wire clk = gen_clk;
main_pll pll_blk (osc_clk, hash_clk);
`else
wire clk = hash_clk;
assign hash_clk = osc_clk;
`endif


//// Hashers
wire [255:0] hash, hash2;
reg is_golden_ticket = 0;
reg [5:0] cnt = 6'd0;
reg feedback = 1'b0;

sha256_transform #(.LOOP(LOOP)) uut (
.clk(clk),
.clk(hash_clk),
.feedback(feedback),
.cnt(cnt),
.rx_state(state),
.rx_input(data),
.tx_hash(hash)
);
sha256_transform #(.LOOP(LOOP)) uut2 (
.clk(clk),
.clk(hash_clk),
.feedback(feedback),
.cnt(cnt),
.rx_state(256'h5be0cd191f83d9ab9b05688c510e527fa54ff53a3c6ef372bb67ae856a09e667),
Expand All @@ -76,35 +88,34 @@ module fpgaminer_top (osc_clk);
//// Virtual Wire Control
reg [255:0] midstate_buf = 0, data_buf = 0;
wire [255:0] midstate_vw, data2_vw;
`ifndef SIM
virtual_wire # (.PROBE_WIDTH(0), .WIDTH(256), .INSTANCE_ID("STAT")) midstate_vw_blk(.probe(), .source(midstate_vw));
virtual_wire # (.PROBE_WIDTH(0), .WIDTH(256), .INSTANCE_ID("DAT2")) data2_vw_blk(.probe(), .source(data2_vw));
`endif

`ifndef SIM
virtual_wire # (.PROBE_WIDTH(0), .WIDTH(256), .INSTANCE_ID("STAT")) midstate_vw_blk(.probe(), .source(midstate_vw));
virtual_wire # (.PROBE_WIDTH(0), .WIDTH(256), .INSTANCE_ID("DAT2")) data2_vw_blk(.probe(), .source(data2_vw));
`endif


//// Virtual Wire Output
reg [31:0] golden_nonce = 0;

`ifndef SIM
virtual_wire # (.PROBE_WIDTH(32), .WIDTH(0), .INSTANCE_ID("GNON")) golden_nonce_vw_blk (.probe(golden_nonce), .source());
virtual_wire # (.PROBE_WIDTH(32), .WIDTH(0), .INSTANCE_ID("NONC")) nonce_vw_blk (.probe(nonce), .source());
`endif


reg [5:0]cnt;
reg feedback, feedback_d1;
wire [5:0]cnt_next;
wire [31:0]nonce_next;
//// Control Unit
reg is_golden_ticket = 1'b0;
reg feedback_d1 = 1'b1;
wire [5:0] cnt_next;
wire [31:0] nonce_next;
wire feedback_next;
`ifndef SIM
wire reset;
assign reset = 1'b0;
`else
reg reset;
`endif

// Note that the nonce reported to the external world will always be
// larger than the real nonce. Currently it is 132 bigger. So an
// external controller (like scripts/mine.tcl) needs to do:
// golden_nonce = golden_nonce - 132
// to get the real nonce.
`ifndef SIM
virtual_wire # (.PROBE_WIDTH(32), .WIDTH(0), .INSTANCE_ID("GNON")) golden_nonce_vw_blk (.probe(golden_nonce), .source());
virtual_wire # (.PROBE_WIDTH(32), .WIDTH(0), .INSTANCE_ID("NONC")) nonce_vw_blk (.probe(nonce), .source());
`endif
`ifndef SIM
wire reset;
assign reset = 1'b0;
`else
reg reset = 1'b0; // NOTE: Reset is not currently used in the actual FPGA; for simulation only.
`endif

assign cnt_next = reset ? 6'd0 : (LOOP == 1) ? 6'd0 : (cnt + 6'd1) & (LOOP-1);
// On the first count (cnt==0), load data from previous stage (no feedback)
Expand All @@ -116,12 +127,11 @@ module fpgaminer_top (osc_clk);
feedback_next ? nonce : (nonce + 32'd1);


//// Control Unit
always @ (posedge clk)
always @ (posedge hash_clk)
begin
`ifdef SIM
midstate_buf <= 256'h2b3f81261b3cfd001db436cfd4c8f3f9c7450c9a0d049bee71cba0ea2619c0b5;
data_buf <= 256'h00000000000000000000000080000000_00000000_39f3001b6b7b8d4dc14bfc31;
//midstate_buf <= 256'h2b3f81261b3cfd001db436cfd4c8f3f9c7450c9a0d049bee71cba0ea2619c0b5;
//data_buf <= 256'h00000000000000000000000080000000_00000000_39f3001b6b7b8d4dc14bfc31;
//nonce <= 30411740;
`else
midstate_buf <= midstate_vw;
Expand All @@ -138,38 +148,23 @@ module fpgaminer_top (osc_clk);
nonce <= nonce_next;



// Check to see if the last hash generated is valid.
is_golden_ticket <= (hash2[255:224] == 32'h00000000) && !feedback_d1;
if(is_golden_ticket)
begin
golden_nonce <= nonce;
// TODO: Find a more compact calculation for this
if (LOOP == 1)
golden_nonce <= nonce - 32'd131;
else if (LOOP == 2)
golden_nonce <= nonce - 32'd66;
else
golden_nonce <= nonce - GOLDEN_NONCE_OFFSET;
end
`ifdef SIM
if (!feedback_d1)
$display ("nonce: %8x\nhash2: %54x\n", nonce, hash2);
$display ("nonce: %8x\nhash2: %64x\n", nonce, hash2);
`endif
end


//// Simulation Clock
`ifdef SIM
initial begin
$dumpfile("test.vcd");
$dumpvars(0,fpgaminer_top);
reset = 1;
#100
#5 gen_clk = 1; #5 gen_clk = 0;
#5 gen_clk = 1; #5 gen_clk = 0;
reset = 0;
#100

repeat(500)
begin
#5 gen_clk = 1; #5 gen_clk = 0;
end
end
`endif

endmodule

2 changes: 2 additions & 0 deletions src/sha-256-functions.v
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
*/


`timescale 1ns/1ps

module e0 (x, y);

input [31:0] x;
Expand Down
40 changes: 26 additions & 14 deletions src/sha256_transform.v
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,34 @@
*
*/


`timescale 1ns/1ps

// A quick define to help index 32-bit words inside a larger register.
`define IDX(x) (((x)+1)*(32)-1):((x)*(32))


// Perform a SHA-256 transformation on the given 512-bit data, and 256-bit
// initial state,
// Outputs one 256-bit hash every 1 cycle.
// Outputs one 256-bit hash every LOOP cycle(s).
//
// The LOOP parameter determines both the size and speed of this module.
// A value of 1 implies a fully unrolled SHA-256 calculation spanning 64 round
// modules and calculating a full SHA-256 hash every clock cycle. A value of
// 2 implies a half-unrolled loop, with 32 round modules and calculating
// a full hash in 2 clock cycles. And so forth.
module sha256_transform #(
parameter LOOP = 6'd4
) (
input clk,
input feedback,
input [5:0]cnt,
input [5:0] cnt,
input [255:0] rx_state,
input [511:0] rx_input,
output reg [255:0] tx_hash
);

// Constants defined by the SHA-2 standard.
localparam Ks = {
32'h428a2f98, 32'h71374491, 32'hb5c0fbcf, 32'he9b5dba5,
32'h3956c25b, 32'h59f111f1, 32'h923f82a4, 32'hab1c5ed5,
Expand All @@ -53,9 +64,7 @@ module sha256_transform #(
32'h391c0cb3, 32'h4ed8aa4a, 32'h5b9cca4f, 32'h682e6ff3,
32'h748f82ee, 32'h78a5636f, 32'h84c87814, 32'h8cc70208,
32'h90befffa, 32'ha4506ceb, 32'hbef9a3f7, 32'hc67178f2};
// How many time to loop on the same logic before advancing to next pipe stage
// At this point please keep this 2^N. We may fix this in the future to allow
// finer granularity in controlling design size


genvar i;

Expand Down Expand Up @@ -89,14 +98,17 @@ module sha256_transform #(

always @ (posedge clk)
begin
tx_hash[`IDX(0)] <= feedback ? tx_hash[`IDX(0)] : (rx_state[`IDX(0)] + HASHERS[64/LOOP-6'd1].state[`IDX(0)]);
tx_hash[`IDX(1)] <= feedback ? tx_hash[`IDX(1)] : (rx_state[`IDX(1)] + HASHERS[64/LOOP-6'd1].state[`IDX(1)]);
tx_hash[`IDX(2)] <= feedback ? tx_hash[`IDX(2)] : (rx_state[`IDX(2)] + HASHERS[64/LOOP-6'd1].state[`IDX(2)]);
tx_hash[`IDX(3)] <= feedback ? tx_hash[`IDX(3)] : (rx_state[`IDX(3)] + HASHERS[64/LOOP-6'd1].state[`IDX(3)]);
tx_hash[`IDX(4)] <= feedback ? tx_hash[`IDX(4)] : (rx_state[`IDX(4)] + HASHERS[64/LOOP-6'd1].state[`IDX(4)]);
tx_hash[`IDX(5)] <= feedback ? tx_hash[`IDX(5)] : (rx_state[`IDX(5)] + HASHERS[64/LOOP-6'd1].state[`IDX(5)]);
tx_hash[`IDX(6)] <= feedback ? tx_hash[`IDX(6)] : (rx_state[`IDX(6)] + HASHERS[64/LOOP-6'd1].state[`IDX(6)]);
tx_hash[`IDX(7)] <= feedback ? tx_hash[`IDX(7)] : (rx_state[`IDX(7)] + HASHERS[64/LOOP-6'd1].state[`IDX(7)]);
if (!feedback)
begin
tx_hash[`IDX(0)] <= rx_state[`IDX(0)] + HASHERS[64/LOOP-6'd1].state[`IDX(0)];
tx_hash[`IDX(1)] <= rx_state[`IDX(1)] + HASHERS[64/LOOP-6'd1].state[`IDX(1)];
tx_hash[`IDX(2)] <= rx_state[`IDX(2)] + HASHERS[64/LOOP-6'd1].state[`IDX(2)];
tx_hash[`IDX(3)] <= rx_state[`IDX(3)] + HASHERS[64/LOOP-6'd1].state[`IDX(3)];
tx_hash[`IDX(4)] <= rx_state[`IDX(4)] + HASHERS[64/LOOP-6'd1].state[`IDX(4)];
tx_hash[`IDX(5)] <= rx_state[`IDX(5)] + HASHERS[64/LOOP-6'd1].state[`IDX(5)];
tx_hash[`IDX(6)] <= rx_state[`IDX(6)] + HASHERS[64/LOOP-6'd1].state[`IDX(6)];
tx_hash[`IDX(7)] <= rx_state[`IDX(7)] + HASHERS[64/LOOP-6'd1].state[`IDX(7)];
end
end


Expand All @@ -106,7 +118,7 @@ endmodule
module sha256_digester (clk, k, rx_w, rx_state, tx_w, tx_state);

input clk;
input [31:0] k;
input [31:0] k;
input [511:0] rx_w;
input [255:0] rx_state;

Expand Down
Loading

0 comments on commit ada8faf

Please sign in to comment.