In progress sha256 integration
diff --git a/verilog/rtl/btc_miner_top.v b/verilog/rtl/btc_miner_top.v
index 1372de4..dcfdb05 100644
--- a/verilog/rtl/btc_miner_top.v
+++ b/verilog/rtl/btc_miner_top.v
@@ -89,16 +89,14 @@
wire [31:0] la_write2;
wire [31:0] la_write3;
- // Bitcoin mining variables
- wire [BITS-1:0] o_nonce;
+ // SHA module variables
+ wire o_error;
wire o_idle;
- logic [639:0] o_block_header;
- wire [255:0] o_target;
- reg [127:0] la_data_out; // TODO
+ reg [127:0] la_data_out; // TODO ensure LA muxing does not require register
// TODO use top 32-bits of LA to control muxing and other variables like starting state machine
- wire [2:0] la_sel;
- assign la_sel = la_data_in[127:125];
+ wire [5:0] la_sel;
+ assign la_sel = la_data_in[127:122];
// WB MI A
assign valid = wbs_cyc_i && wbs_stb_i;
@@ -107,7 +105,7 @@
assign wdata = wbs_dat_i;
// IO
- assign io_out = o_nonce;
+ assign io_out = rdata;
assign io_oeb = {(`MPRJ_IO_PADS-1){rst}};
// IRQ
@@ -120,23 +118,21 @@
assign la_write2 = ~la_oenb[95:64] & ~{BITS{valid}};
assign la_write3 = ~la_oenb[127:96] & ~{BITS{valid}};
- // Assuming LA probes [97:96] are for controlling the clk & reset
- assign clk = (~la_oenb[96]) ? la_data_in[96] : wb_clk_i;
- assign rst = (~la_oenb[97]) ? la_data_in[97] : wb_rst_i;
+ // Assuming LA probes [107:106] are for controlling the clk & reset
+ assign clk = (~la_oenb[106]) ? la_data_in[106] : wb_clk_i;
+ assign rst = (~la_oenb[107]) ? la_data_in[107] : wb_rst_i;
// TODO more LA muxing
// la_data_in or la_data_out or la_oenb or la_sel or nonce or block_header or target
- always @(la_data_in || la_oenb || la_sel || o_nonce || o_block_header || o_target) begin
+ always @(la_data_in || la_oenb || la_sel || rdata || o_error || o_idle) begin
case (la_sel)
- 3'b000:
- la_data_out[95:0] <= {{(95-BITS){1'b0}}, o_nonce};
- 3'b001:
- la_data_out[95:0] <= o_block_header[95:0];
- 3'b010:
- la_data_out[95:0] <= o_block_header[191:96];
- 3'b011:
- la_data_out[95:0] <= o_block_header[287:192];
+ 6'b000000:
+ la_data_out[95:0] <= {{(95-(BITS-2)){1'b0}}, {o_idle, o_error, rdata}};
+ default:
+ begin
+ // nothing
+ end
endcase
end
@@ -147,17 +143,13 @@
.clk(clk),
.rst(rst),
.valid(valid),
- .wb_we(wbs_we_i),
+ .wb_wr_mask(wstrb),
.wdata(wbs_dat_i),
- .la_write0(la_write0),
.la_write3(la_write3),
- .la_input0(la_data_in[31:0]),
.la_input3(la_data_in[127:96]),
- .ready(wbs_ack_o),
.rdata(rdata),
- .block_header(o_block_header),
- .target(o_target),
- .nonce(o_nonce),
+ .ready(wbs_ack_o),
+ .error(o_error),
.idle(o_idle)
);
@@ -168,46 +160,67 @@
module miner_ctrl #(
parameter BITS = 32
)(
- input clk,
- input rst,
- input valid,
- input wb_we,
- input [BITS-1:0] wdata,
- input [BITS-1:0] la_write0,
- input [BITS-1:0] la_write3,
- input [BITS-1:0] la_input0,
- input [BITS-1:0] la_input3,
- output ready,
- output [BITS-1:0] rdata,
- output [639:0] block_header,
- output [255:0] target,
- output [BITS-1:0] nonce,
- output idle
+ input wire clk,
+ input wire rst,
+ input wire valid,
+ input wire [3:0] wb_wr_mask,
+ input wire [BITS-1:0] wdata,
+ input wire [BITS-1:0] la_write3,
+ input wire [BITS-1:0] la_input3,
+ output reg [BITS-1:0] rdata,
+ output reg ready,
+ output wire error,
+ output wire idle
);
- // enum logic [1:0] {WAIT_IN=2'b00, READ_IN=2'b01, COMPUTE=2'b10, CHECK=2'b11, WRITE_OUT=} state;
- // enum integer unsigned {WAIT_IN=0, READ_IN=1, COMPUTE=2, INCR_NONCE=3, WRITE_OUT=4} state;
- localparam WAIT_IN=0, READ_IN=1, COMPUTE=2, INCR_NONCE=3, WRITE_OUT=4;
+ // sha256 internal constants and parameters
+ localparam ADDR_NAME0 = 8'h00;
+ localparam ADDR_NAME1 = 8'h01;
+ localparam ADDR_VERSION = 8'h02;
+
+ localparam ADDR_CTRL = 8'h08;
+ localparam CTRL_INIT_BIT = 0;
+ localparam CTRL_NEXT_BIT = 1;
+ localparam CTRL_MODE_BIT = 2;
+
+ localparam ADDR_STATUS = 8'h09;
+ localparam STATUS_READY_BIT = 0;
+ localparam STATUS_VALID_BIT = 1;
+
+ localparam ADDR_BLOCK0 = 8'h10;
+ localparam ADDR_BLOCK15 = 8'h1f;
+
+ localparam ADDR_DIGEST0 = 8'h20;
+ localparam ADDR_DIGEST7 = 8'h27;
+
+ localparam MODE_SHA_224 = 1'h0;
+ localparam MODE_SHA_256 = 1'h1;
+
+ // enum logic [1:0] {WAIT_IN=2'b00, READ_IN=2'b01, WAIT_COMPUTE=2'b10, CHECK=2'b11, WRITE_OUT=} state;
+ // enum integer unsigned {WAIT_IN=0, READ_IN=1, WAIT_COMPUTE=2, INCR_NONCE=3, WRITE_OUT=4} state;
+ localparam WAIT_IN=0, READ_IN=1, WAIT_COMPUTE=2, WRITE_OUT=3;
reg [2:0] state;
- reg ready;
- reg [BITS-1:0] rdata;
- reg [BITS-1:0] wb_data_reg;
- reg [BITS-1:0] nonce;
- reg [BITS-1:0] encoded_target;
- reg [255:0] target;
- reg miner_rst;
+ wire start_ctrl;
+ wire sha_cs;
+ wire sha_we;
+ wire [7:0] sha_address;
+ wire [BITS-1:0] sha_write_data;
+ wire [BITS-1:0] sha_read_data;
- logic [639:0] block_header;
- logic [255:0] o_hash_val;
- logic o_done_hash;
-
- wire idle;
- wire start;
+ wire sha_in_ready;
+ wire sha_digest_valid;
+ wire auto_ctrl;
assign idle = (state == WAIT_IN) ? 1'b1 : 1'b0;
- assign start = la_write3[2] ? la_input3[2] : 1'b0;
+ assign start_ctrl = la_input3[12] & la_write3[12];
+
+ assign sha_cs = la_input3[8] & la_write3[8];
+ assign sha_we = la_input3[9] & la_write3[9];
+ assign sha_address = la_input3[7:0] & la_write3[7:0];
+
+ assign auto_ctrl = la_input3[13] & la_write3[13];
// need to count to 640/32 = 20 (decimal). Only to 19 b/c nonce is last 32-bits
integer unsigned count;
@@ -216,108 +229,41 @@
if (rst) begin
ready <= 0;
rdata <= 0;
- wb_data_reg <= 0;
- nonce <= 0;
- encoded_target <= 0;
- target <= 0;
count <= 0;
- miner_rst <= 1;
- block_header <= 0;
state <= WAIT_IN;
- end else begin
+ end else if (auto_ctrl) begin
ready <= 1'b0;
// state machine for controlling miner and I/O
case (state)
WAIT_IN: begin
// TODO?
- miner_rst <= 1;
- if (start == 1) begin
+ if (start_ctrl) begin
state <= READ_IN;
end
end
READ_IN: begin
- // TODO
- miner_rst <= 1;
-
+ // TODO?
if (valid && !ready) begin
ready <= 1'b1;
- if (wb_we) begin
- // TODO read WB data into block header
- if (count == 0) begin
- block_header[BITS-1:0] <= wdata;
- count <= count + 1;
- end else if (count == 1) begin
- block_header[BITS*2-1:BITS] <= wdata;
- count <= count + 1;
- end else if (count == 2) begin
- block_header[BITS*3-1:BITS*2] <= wdata;
- count <= count + 1;
- end else if (count == 3) begin
- block_header[BITS*4-1:BITS*3] <= wdata;
- count <= count + 1;
- end else if (count == 4) begin
- block_header[BITS*5-1:BITS*4] <= wdata;
- count <= count + 1;
- end else if (count == 5) begin
- block_header[BITS*6-1:BITS*5] <= wdata;
- count <= count + 1;
- end else if (count == 6) begin
- block_header[BITS*7-1:BITS*6] <= wdata;
- count <= count + 1;
- end else if (count == 7) begin
- block_header[BITS*8-1:BITS*7] <= wdata;
- count <= count + 1;
- end else if (count == 8) begin
- block_header[BITS*9-1:BITS*8] <= wdata;
- count <= count + 1;
- end else if (count == 9) begin
- block_header[BITS*10-1:BITS*9] <= wdata;
- count <= count + 1;
- end
-
- if (count == 18) begin
- // TODO pass encoded_target into decoder module
- encoded_target <= wdata;
- target <= {{(255-BITS){1'b0}}, wdata};
- count <= count + 1;
- end else if (count >= 19) begin
- block_header[639:608] <= nonce;
- count <= 0;
- nonce <= nonce + 1;
- miner_rst <= 0;
- state <= COMPUTE;
- end else begin
- count <= count + 1;
+ if (wb_wr_mask == 4'b1111) begin
+ // if read up to the last address
+ if ((sha_address == ADDR_BLOCK15) && sha_cs && !sha_we) begin
+ state <= WAIT_COMPUTE;
end
end
end
end
- COMPUTE: begin
- // start miner
- if (o_done_hash) begin
- // TODO target
- if (o_hash_val < target) begin
- state <= WRITE_OUT;
- end else begin
- miner_rst <= 1;
- block_header[639:608] <= nonce;
- state <= INCR_NONCE;
- end
- end else begin
- miner_rst <= 0;
- end
- end
+ WAIT_COMPUTE: begin
+ // read status register to determine when done
+ if (sha_cs && !sha_we) begin
+ // TODO read status register and move to WRITE_OUT state
- INCR_NONCE: begin
- // TODO?
- miner_rst <= 0;
- nonce <= nonce + 1;
- state <= COMPUTE;
+ end
end
WRITE_OUT: begin
@@ -325,247 +271,32 @@
if (valid && !ready) begin
ready <= 1'b1;
- if (wb_we) begin
+ if (wb_wr_mask == 4'b1111) begin
// WB should not be writing to user project
end else begin
// Place output hash on wishbone
- rdata <= o_hash_val[BITS*count +:BITS];
- if (count >= 7) begin
- count <= 0;
- state <= WAIT_IN;
- end else begin
- count <= count + 1;
- end
end
end
end
endcase
+ end else begin
+ // TODO not automated control. FW controls all wr/rd and addresses.
end
end
- miner double_sha256_miner(
- .block(block_header),
+ // TODO
+ sha256 sha256_inst0(
.clk(clk),
- .rst(rst),
- .hashed(o_hash_val),
- .done(o_done_hash)
+ .reset_n(~rst),
+ .cs(sha_cs),
+ .we(sha_we),
+ .address(sha_address),
+ .write_data(sha_write_data),
+ .read_data(sha_read_data),
+ .error(error)
);
+
endmodule // miner_ctrl
-
-// miner
-module miner(
- input logic [639:0] block,
- input logic clk, rst,
- output logic [255:0] hashed,
- output logic done
-);
-
- logic [255:0] first_hash;
- logic [255:0] secnd_hash;
-
- logic second_run_rst;
- logic done_first_hash;
- logic done_secnd_hash;
-
- sha_256 #(.MSG_SIZE(640), .PADDED_SIZE(1024)) first (.message(block), .hashed(first_hash), .clk(clk), .rst(rst), .done(done_first_hash));
- sha_256 #(.MSG_SIZE(256), .PADDED_SIZE(512)) second (.message(first_hash), .hashed(secnd_hash), .clk(clk), .rst(second_run_rst), .done(done_secnd_hash));
-
- // always @* second_run_rst <= 1'b0;
-
- always @(posedge clk) begin
- if (done_first_hash === 1'bX) second_run_rst <= 1'b1;
- else if (done_first_hash == 1'b1) second_run_rst <= 1'b0;
- end
-
- assign done = done_secnd_hash;
- assign hashed = {secnd_hash[7:0], secnd_hash[15:8], secnd_hash[23:16], secnd_hash[31:24], secnd_hash[39:32], secnd_hash[47:40], secnd_hash[55:48], secnd_hash[63:56], secnd_hash[71:64], secnd_hash[79:72], secnd_hash[87:80], secnd_hash[95:88], secnd_hash[103:96], secnd_hash[111:104], secnd_hash[119:112], secnd_hash[127:120], secnd_hash[135:128], secnd_hash[143:136], secnd_hash[151:144], secnd_hash[159:152], secnd_hash[167:160], secnd_hash[175:168], secnd_hash[183:176], secnd_hash[191:184], secnd_hash[199:192], secnd_hash[207:200], secnd_hash[215:208], secnd_hash[223:216], secnd_hash[231:224], secnd_hash[239:232], secnd_hash[247:240], secnd_hash[255:248]};
-endmodule // miner
-
-
-// sha_256
-module sha_256 #(
- parameter MSG_SIZE = 24,
- parameter PADDED_SIZE = 512
-)(
- input logic [MSG_SIZE-1:0] message,
- input logic clk, rst,
- output logic [255:0] hashed,
- output logic done
-);
-
- logic[PADDED_SIZE-1:0] padded;
-
- sha_padder #(.MSG_SIZE(MSG_SIZE), .PADDED_SIZE(PADDED_SIZE)) padder (.message(message), .padded(padded));
- // sha_mainloop #(.PADDED_SIZE(PADDED_SIZE)) loop (.padded(padded), .hashed(hashed), .clk(clk), .rst(rst), .done(done));
- assign hashed = 0;
- assign done = 0;
-endmodule // sha_256
-
-
-// sha_padder
-`define PACK_ARRAY(PK_WIDTH,PK_LEN,PK_SRC,PK_DEST) genvar pk_idx; generate for (pk_idx=0; pk_idx<(PK_LEN); pk_idx=pk_idx+1) begin; assign PK_DEST[((PK_WIDTH)*pk_idx+((PK_WIDTH)-1)):((PK_WIDTH)*pk_idx)] = PK_SRC[pk_idx][((PK_WIDTH)-1):0]; end; endgenerate
-`define UNPACK_ARRAY(PK_WIDTH,PK_LEN,PK_DEST,PK_SRC) genvar unpk_idx; generate for (unpk_idx=0; unpk_idx<(PK_LEN); unpk_idx=unpk_idx+1) begin; assign PK_DEST[unpk_idx][((PK_WIDTH)-1):0] = PK_SRC[((PK_WIDTH)*unpk_idx+(PK_WIDTH-1)):((PK_WIDTH)*unpk_idx)]; end; endgenerate
-
-module sha_padder #(
- parameter MSG_SIZE = 24, // size of full message
- parameter PADDED_SIZE = 512
-)(
- input logic [MSG_SIZE-1:0] message,
- output logic [PADDED_SIZE-1:0] padded
-);
-
- localparam zero_width = PADDED_SIZE-MSG_SIZE-1-64;
- localparam back_0_width = 64-$bits(MSG_SIZE);
-
- assign padded = {message, 1'b1, {zero_width{1'b0}}, {back_0_width{1'b0}}, MSG_SIZE};
-endmodule //sha_padder
-
-
-// sha_mainloop
-module sha_mainloop #(
- parameter PADDED_SIZE = 512
-)(
- input logic [PADDED_SIZE-1:0] padded,
- input logic clk, rst,
- output logic [255:0] hashed,
- output logic done
-);
-
- function [31:0] K;
- input [6:0] x;
- K = k[2047-x*32 -: 32];
- endfunction
-
- function automatic [31:0] W;
- input [6:0] x;
- input [6:0] y;
- if(^x === 1'bX) W = 32'h777;
- else W = (x<16) ? padded[((PADDED_SIZE-1-y*512)-x*32) -: 32] : rho1(W(x-2, y)) + W(x-7, y) + rho0(W(x-15, y)) + W(x-16, y);
- endfunction
-
- function automatic [31:0] rho0;
- input [31:0] x;
- if(^x === 1'bX) rho0 = 32'h888;
- else rho0 = {x[6:0],x[31:7]} ^ {x[17:0],x[31:18]} ^ (x >> 3);
- endfunction
-
- function automatic [31:0] rho1;
- input [31:0] x;
- if(^x === 1'bX) rho1 = 32'h888;
- else rho1 = {x[16:0],x[31:17]} ^ {x[18:0],x[31:19]} ^ (x >> 10);
- endfunction
-
- function [31:0] ch;
- input [31:0] x,y,z;
- if(^x === 1'bX) ch = 32'h888;
- else ch = (x & y) ^ (~x & z);
- endfunction
-
- function [31:0] maj;
- input [31:0] x,y,z;
- if(^x === 1'bX) maj = 32'h888;
- else maj = (x & y) ^ (x & z) ^ (y & z);
- endfunction
-
- function [31:0] sum0;
- input [31:0] x;
- if(^x === 1'bX) sum0 = 32'h888;
- else sum0 = {x[1:0],x[31:2]} ^ {x[12:0],x[31:13]} ^ {x[21:0],x[31:22]};
- endfunction
-
- function [31:0] sum1;
- input [31:0] x;
- if(^x === 1'bX) sum1 = 32'h888;
- else sum1 = {x[5:0],x[31:6]} ^ {x[10:0],x[31:11]} ^ {x[24:0],x[31:25]};
- endfunction
-
- logic [255:0] initial_hashes = {32'h6a09e667, 32'hbb67ae85, 32'h3c6ef372, 32'ha54ff53a, 32'h510e527f, 32'h9b05688c, 32'h1f83d9ab, 32'h5be0cd19};
-
- logic [2047:0] k = {32'h428a2f98, 32'h71374491, 32'hb5c0fbcf, 32'he9b5dba5, 32'h3956c25b, 32'h59f111f1, 32'h923f82a4, 32'hab1c5ed5, 32'hd807aa98, 32'h12835b01, 32'h243185be, 32'h550c7dc3, 32'h72be5d74, 32'h80deb1fe, 32'h9bdc06a7, 32'hc19bf174, 32'he49b69c1, 32'hefbe4786, 32'h0fc19dc6, 32'h240ca1cc, 32'h2de92c6f, 32'h4a7484aa, 32'h5cb0a9dc, 32'h76f988da, 32'h983e5152, 32'ha831c66d, 32'hb00327c8, 32'hbf597fc7, 32'hc6e00bf3, 32'hd5a79147, 32'h06ca6351, 32'h14292967, 32'h27b70a85, 32'h2e1b2138, 32'h4d2c6dfc, 32'h53380d13, 32'h650a7354, 32'h766a0abb, 32'h81c2c92e, 32'h92722c85, 32'ha2bfe8a1, 32'ha81a664b, 32'hc24b8b70, 32'hc76c51a3, 32'hd192e819, 32'hd6990624, 32'hf40e3585, 32'h106aa070, 32'h19a4c116, 32'h1e376c08, 32'h2748774c, 32'h34b0bcb5, 32'h391c0cb3, 32'h4ed8aa4a, 32'h5b9cca4f, 32'h682e6ff3, 32'h748f82ee, 32'h78a5636f, 32'h84c87814, 32'h8cc70208, 32'h90befffa, 32'ha4506ceb, 32'hbef9a3f7, 32'hc67178f2};
-
- logic [31:0] a, b, c, d, e, f, g, h, t1, t2;
- logic [31:0] h1, h2, h3, h4, h5, h6, h7, h8;
-
- logic [6:0] j;
- logic [6:0] i;
-
- localparam N = PADDED_SIZE/512; // number of blocks
-
- logic [31:0] ch_efg, maj_abc, sum0_a, sum1_e, kj, wj;
-
- // (e or f or g or ch_efg)
- always_comb begin
- ch_efg = ch(e,f,g);
- maj_abc = maj(a,b,c);
- sum0_a = sum0(a);
- sum1_e = sum1(e);
- wj = W(j, i);
- kj = K(j);
- end
-
- always @(negedge clk) begin
- // t1 <= h + sum1(e) + ch(e,f,g) + K(j) + W(j);
- // t2 <= sum0(a) + maj(a,b,c);
- t1 <= (h + sum1_e + ch_efg + kj + wj)%4294967296;
- t2 <= (sum0_a + maj_abc)%4294967296;
- end
-
- always @(posedge clk or posedge rst) begin
- if(rst) begin
- i <= 1'b0;
- j <= 1'bX;
- h1 <= 32'h6a09e667;
- h2 <= 32'hbb67ae85;
- h3 <= 32'h3c6ef372;
- h4 <= 32'ha54ff53a;
- h5 <= 32'h510e527f;
- h6 <= 32'h9b05688c;
- h7 <= 32'h1f83d9ab;
- h8 <= 32'h5be0cd19;
- end
- else if (^j === 1'bX && ^i !== 1'bX) begin
- a <= h1;
- b <= h2;
- c <= h3;
- d <= h4;
- e <= h5;
- f <= h6;
- g <= h7;
- h <= h8;
- j <= 1'd0;
- end
- else if (j < 64) begin
- h <= g;
- g <= f;
- f <= e;
- e <= (d+t1)%4294967296;
- d <= c;
- c <= b;
- b <= a;
- a <= (t1+t2)%4294967296;
- j <= j+1;
- end
- else if (j == 64) begin
- h1 <= a + h1;
- h2 <= b + h2;
- h3 <= c + h3;
- h4 <= d + h4;
- h5 <= e + h5;
- h6 <= f + h6;
- h7 <= g + h7;
- h8 <= h + h8;
- j <= 1'bX;
- if (i<N-1) i <= i+1;
- else begin
- i <= 1'bX;
- done <= 1'b1;
- end
- end
- end
-
- assign hashed = {h1, h2, h3, h4, h5, h6, h7, h8};
-endmodule // sha_mainloop
-
`default_nettype wire
diff --git a/verilog/rtl/btc_miner_top_old.v b/verilog/rtl/btc_miner_top_old.v
new file mode 100644
index 0000000..19bb0d1
--- /dev/null
+++ b/verilog/rtl/btc_miner_top_old.v
@@ -0,0 +1,575 @@
+// SPDX-FileCopyrightText: 2020 Efabless Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
+
+`default_nettype none
+/*
+ *-------------------------------------------------------------
+ *
+ * btc_miner_top
+ * TODO!
+ *
+ * This is an example of a (trivially simple) user project,
+ * showing how the user project can connect to the logic
+ * analyzer, the wishbone bus, and the I/O pads.
+ *
+ * This project generates an integer count, which is output
+ * on the user area GPIO pads (digital output only). The
+ * wishbone connection allows the project to be controlled
+ * (start and stop) from the management SoC program.
+ *
+ * See the testbenches in directory "mprj_counter" for the
+ * example programs that drive this user project. The three
+ * testbenches are "io_ports", "la_test1", and "la_test2".
+ *
+ *-------------------------------------------------------------
+ */
+
+module btc_miner_top #(
+ parameter BITS = 32
+)(
+`ifdef USE_POWER_PINS
+ inout vccd1, // User area 1 1.8V supply
+ inout vssd1, // User area 1 digital ground
+`endif
+
+ // Wishbone Slave ports (WB MI A)
+ input wb_clk_i,
+ input wb_rst_i,
+ input wbs_stb_i,
+ input wbs_cyc_i,
+ input wbs_we_i,
+ input [3:0] wbs_sel_i,
+ input [31:0] wbs_dat_i,
+ input [31:0] wbs_adr_i,
+ output wbs_ack_o,
+ output [31:0] wbs_dat_o,
+
+ // Logic Analyzer Signals
+ input [127:0] la_data_in,
+ output [127:0] la_data_out,
+ input [127:0] la_oenb,
+
+ // IOs
+ input [`MPRJ_IO_PADS-1:0] io_in,
+ output [`MPRJ_IO_PADS-1:0] io_out,
+ output [`MPRJ_IO_PADS-1:0] io_oeb,
+
+ // IRQ
+ output [2:0] irq
+);
+ wire clk;
+ wire rst;
+
+ wire [`MPRJ_IO_PADS-1:0] io_in;
+ wire [`MPRJ_IO_PADS-1:0] io_out;
+ wire [`MPRJ_IO_PADS-1:0] io_oeb;
+
+ // WB wires
+ wire [31:0] rdata;
+ wire [31:0] wdata;
+
+ wire valid;
+ wire [3:0] wstrb;
+
+ // LA wires
+ wire [31:0] la_write0;
+ wire [31:0] la_write1;
+ wire [31:0] la_write2;
+ wire [31:0] la_write3;
+
+ // Bitcoin mining variables
+ wire [BITS-1:0] o_nonce;
+ wire o_idle;
+ wire [639:0] o_block_header;
+ wire [255:0] o_target;
+ reg [127:0] la_data_out; // TODO ensure LA muxing does not require register
+
+ // TODO use top 32-bits of LA to control muxing and other variables like starting state machine
+ wire [5:0] la_sel;
+ assign la_sel = la_data_in[127:122];
+
+ // WB MI A
+ assign valid = wbs_cyc_i && wbs_stb_i;
+ assign wstrb = wbs_sel_i & {4{wbs_we_i}};
+ assign wbs_dat_o = rdata;
+ assign wdata = wbs_dat_i;
+
+ // IO
+ assign io_out = o_nonce;
+ assign io_oeb = {(`MPRJ_IO_PADS-1){rst}};
+
+ // IRQ
+ assign irq = 3'b000; // Unused
+
+ // Assuming LA probes [31:0] (aka: la_write0) are for controlling the nonce register.
+ // * NOTE: These are used as a mask for the la_data_in[?:?]
+ assign la_write0 = ~la_oenb[31:0] & ~{BITS{valid}};
+ assign la_write1 = ~la_oenb[63:32] & ~{BITS{valid}};
+ assign la_write2 = ~la_oenb[95:64] & ~{BITS{valid}};
+ assign la_write3 = ~la_oenb[127:96] & ~{BITS{valid}};
+
+ // Assuming LA probes [107:106] are for controlling the clk & reset
+ assign clk = (~la_oenb[106]) ? la_data_in[106] : wb_clk_i;
+ assign rst = (~la_oenb[107]) ? la_data_in[107] : wb_rst_i;
+
+ // TODO more LA muxing
+ // la_data_in or la_data_out or la_oenb or la_sel or nonce or block_header or target
+ always @(la_data_in || la_oenb || la_sel || o_nonce || o_block_header || o_target) begin
+ case (la_sel)
+ 6'b000000:
+ la_data_out[95:0] <= {{(95-BITS){1'b0}}, o_nonce};
+ 6'b000001:
+ la_data_out[95:0] <= o_block_header[95:0];
+ 6'b000010:
+ la_data_out[95:0] <= o_block_header[191:96];
+ 6'b000011:
+ la_data_out[95:0] <= o_block_header[287:192];
+
+ default:
+ begin
+ // nothing
+ end
+ endcase
+ end
+
+ // TODO create state machine for reading block header and passing to miner
+ miner_ctrl #(
+ .BITS(BITS)
+ ) miner_ctrl(
+ .clk(clk),
+ .rst(rst),
+ .valid(valid),
+ .wb_we(wbs_we_i),
+ .wdata(wbs_dat_i),
+ .la_write0(la_write0),
+ .la_write3(la_write3),
+ .la_input0(la_data_in[31:0]),
+ .la_input3(la_data_in[127:96]),
+ .ready(wbs_ack_o),
+ .rdata(rdata),
+ .block_header(o_block_header),
+ .target(o_target),
+ .nonce(o_nonce),
+ .idle(o_idle)
+ );
+
+endmodule // btc_miner_top
+
+
+// miner_ctrl
+module miner_ctrl #(
+ parameter BITS = 32
+)(
+ input clk,
+ input rst,
+ input valid,
+ input wb_we,
+ input [BITS-1:0] wdata,
+ input [BITS-1:0] la_write0,
+ input [BITS-1:0] la_write3,
+ input [BITS-1:0] la_input0,
+ input [BITS-1:0] la_input3,
+ output ready,
+ output [BITS-1:0] rdata,
+ output [639:0] block_header,
+ output [255:0] target,
+ output [BITS-1:0] nonce,
+ output idle
+);
+
+ // enum logic [1:0] {WAIT_IN=2'b00, READ_IN=2'b01, COMPUTE=2'b10, CHECK=2'b11, WRITE_OUT=} state;
+ // enum integer unsigned {WAIT_IN=0, READ_IN=1, COMPUTE=2, INCR_NONCE=3, WRITE_OUT=4} state;
+ localparam WAIT_IN=0, READ_IN=1, COMPUTE=2, INCR_NONCE=3, WRITE_OUT=4;
+
+ reg [2:0] state;
+
+ reg ready;
+ reg [BITS-1:0] rdata;
+ reg [BITS-1:0] wb_data_reg;
+ reg [BITS-1:0] nonce;
+ reg [BITS-1:0] encoded_target;
+ reg [255:0] target;
+ reg miner_rst;
+
+ reg [639:0] block_header;
+ reg [255:0] o_hash_val;
+ reg o_done_hash;
+
+ wire idle;
+ wire start_ctrl;
+
+ assign idle = (state == WAIT_IN) ? 1'b1 : 1'b0;
+ assign start_ctrl = la_write3[12] ? la_input3[12] : 1'b0;
+
+ // need to count to 640/32 = 20 (decimal). Only to 19 b/c nonce is last 32-bits
+ integer unsigned count;
+
+ always @(posedge clk) begin
+ if (rst) begin
+ ready <= 0;
+ rdata <= 0;
+ wb_data_reg <= 0;
+ nonce <= 0;
+ encoded_target <= 0;
+ target <= 0;
+ count <= 0;
+ miner_rst <= 1;
+ block_header <= 0;
+
+ state <= WAIT_IN;
+ end else begin
+ ready <= 1'b0;
+
+ // state machine for controlling miner and I/O
+ case (state)
+ WAIT_IN: begin
+ // TODO?
+ miner_rst <= 1;
+ if (start_ctrl == 1) begin
+ state <= READ_IN;
+ end
+ end
+
+ READ_IN: begin
+ // TODO
+ miner_rst <= 1;
+
+ if (valid && !ready) begin
+ ready <= 1'b1;
+
+ if (wb_we) begin
+ // TODO read WB data into block header
+ if (count == 0) begin
+ block_header[BITS-1:0] <= wdata;
+ count <= count + 1;
+ end else if (count == 1) begin
+ block_header[BITS*2-1:BITS] <= wdata;
+ count <= count + 1;
+ end else if (count == 2) begin
+ block_header[BITS*3-1:BITS*2] <= wdata;
+ count <= count + 1;
+ end else if (count == 3) begin
+ block_header[BITS*4-1:BITS*3] <= wdata;
+ count <= count + 1;
+ end else if (count == 4) begin
+ block_header[BITS*5-1:BITS*4] <= wdata;
+ count <= count + 1;
+ end else if (count == 5) begin
+ block_header[BITS*6-1:BITS*5] <= wdata;
+ count <= count + 1;
+ end else if (count == 6) begin
+ block_header[BITS*7-1:BITS*6] <= wdata;
+ count <= count + 1;
+ end else if (count == 7) begin
+ block_header[BITS*8-1:BITS*7] <= wdata;
+ count <= count + 1;
+ end else if (count == 8) begin
+ block_header[BITS*9-1:BITS*8] <= wdata;
+ count <= count + 1;
+ end else if (count == 9) begin
+ block_header[BITS*10-1:BITS*9] <= wdata;
+ count <= count + 1;
+ end
+
+ if (count == 18) begin
+ // TODO pass encoded_target into decoder module
+ encoded_target <= wdata;
+ target <= {{(255-BITS){1'b0}}, wdata};
+ count <= count + 1;
+ end else if (count >= 19) begin
+ block_header[639:608] <= nonce;
+ count <= 0;
+ nonce <= nonce + 1;
+ miner_rst <= 0;
+ state <= COMPUTE;
+ end else begin
+ count <= count + 1;
+ end
+ end
+ end
+ end
+
+ COMPUTE: begin
+ // start miner
+ if (o_done_hash) begin
+ // TODO target
+ if (o_hash_val < target) begin
+ state <= WRITE_OUT;
+ end else begin
+ miner_rst <= 1;
+ block_header[639:608] <= nonce;
+ state <= INCR_NONCE;
+ end
+ end else begin
+ miner_rst <= 0;
+ end
+ end
+
+ INCR_NONCE: begin
+ // TODO?
+ miner_rst <= 0;
+ nonce <= nonce + 1;
+ state <= COMPUTE;
+ end
+
+ WRITE_OUT: begin
+ // TODO
+ if (valid && !ready) begin
+ ready <= 1'b1;
+
+ if (wb_we) begin
+ // WB should not be writing to user project
+ end else begin
+ // Place output hash on wishbone
+ rdata <= o_hash_val[BITS*count +:BITS];
+ if (count >= 7) begin
+ count <= 0;
+ state <= WAIT_IN;
+ end else begin
+ count <= count + 1;
+ end
+ end
+ end
+ end
+
+ endcase
+ end
+ end
+
+ miner double_sha256_miner(
+ .block(block_header),
+ .clk(clk),
+ .rst(rst),
+ .hashed(o_hash_val),
+ .done(o_done_hash)
+ );
+endmodule // miner_ctrl
+
+
+// miner
+module miner(
+ input logic [639:0] block,
+ input logic clk, rst,
+ output logic [255:0] hashed,
+ output logic done
+);
+
+ logic [255:0] first_hash;
+ logic [255:0] secnd_hash;
+
+ logic second_run_rst;
+ logic done_first_hash;
+ logic done_secnd_hash;
+
+ sha_256 #(.MSG_SIZE(640), .PADDED_SIZE(1024)) first (.message(block), .hashed(first_hash), .clk(clk), .rst(rst), .done(done_first_hash));
+ sha_256 #(.MSG_SIZE(256), .PADDED_SIZE(512)) second (.message(first_hash), .hashed(secnd_hash), .clk(clk), .rst(second_run_rst), .done(done_secnd_hash));
+
+ // always @* second_run_rst <= 1'b0;
+
+ always @(posedge clk) begin
+ if (done_first_hash === 1'bX) second_run_rst <= 1'b1;
+ else if (done_first_hash == 1'b1) second_run_rst <= 1'b0;
+ end
+
+ assign done = done_secnd_hash;
+ assign hashed = {secnd_hash[7:0], secnd_hash[15:8], secnd_hash[23:16], secnd_hash[31:24], secnd_hash[39:32], secnd_hash[47:40], secnd_hash[55:48], secnd_hash[63:56], secnd_hash[71:64], secnd_hash[79:72], secnd_hash[87:80], secnd_hash[95:88], secnd_hash[103:96], secnd_hash[111:104], secnd_hash[119:112], secnd_hash[127:120], secnd_hash[135:128], secnd_hash[143:136], secnd_hash[151:144], secnd_hash[159:152], secnd_hash[167:160], secnd_hash[175:168], secnd_hash[183:176], secnd_hash[191:184], secnd_hash[199:192], secnd_hash[207:200], secnd_hash[215:208], secnd_hash[223:216], secnd_hash[231:224], secnd_hash[239:232], secnd_hash[247:240], secnd_hash[255:248]};
+endmodule // miner
+
+
+// sha_256
+module sha_256 #(
+ parameter MSG_SIZE = 24,
+ parameter PADDED_SIZE = 512
+)(
+ input logic [MSG_SIZE-1:0] message,
+ input logic clk, rst,
+ output logic [255:0] hashed,
+ output logic done
+);
+
+ logic[PADDED_SIZE-1:0] padded;
+
+ sha_padder #(.MSG_SIZE(MSG_SIZE), .PADDED_SIZE(PADDED_SIZE)) padder (.message(message), .padded(padded));
+ // sha_mainloop #(.PADDED_SIZE(PADDED_SIZE)) loop (.padded(padded), .hashed(hashed), .clk(clk), .rst(rst), .done(done));
+ assign hashed = 0;
+ assign done = 0;
+endmodule // sha_256
+
+
+// sha_padder
+`define PACK_ARRAY(PK_WIDTH,PK_LEN,PK_SRC,PK_DEST) genvar pk_idx; generate for (pk_idx=0; pk_idx<(PK_LEN); pk_idx=pk_idx+1) begin; assign PK_DEST[((PK_WIDTH)*pk_idx+((PK_WIDTH)-1)):((PK_WIDTH)*pk_idx)] = PK_SRC[pk_idx][((PK_WIDTH)-1):0]; end; endgenerate
+`define UNPACK_ARRAY(PK_WIDTH,PK_LEN,PK_DEST,PK_SRC) genvar unpk_idx; generate for (unpk_idx=0; unpk_idx<(PK_LEN); unpk_idx=unpk_idx+1) begin; assign PK_DEST[unpk_idx][((PK_WIDTH)-1):0] = PK_SRC[((PK_WIDTH)*unpk_idx+(PK_WIDTH-1)):((PK_WIDTH)*unpk_idx)]; end; endgenerate
+
+module sha_padder #(
+ parameter MSG_SIZE = 24, // size of full message
+ parameter PADDED_SIZE = 512
+)(
+ input logic [MSG_SIZE-1:0] message,
+ output logic [PADDED_SIZE-1:0] padded
+);
+
+ localparam zero_width = PADDED_SIZE-MSG_SIZE-1-64;
+ localparam back_0_width = 64-$bits(MSG_SIZE);
+
+ assign padded = {message, 1'b1, {zero_width{1'b0}}, {back_0_width{1'b0}}, MSG_SIZE};
+endmodule //sha_padder
+
+
+// sha_mainloop
+module sha_mainloop #(
+ parameter PADDED_SIZE = 512
+)(
+ input logic [PADDED_SIZE-1:0] padded,
+ input logic clk, rst,
+ output logic [255:0] hashed,
+ output logic done
+);
+
+ function [31:0] K;
+ input [6:0] x;
+ K = k[2047-x*32 -: 32];
+ endfunction
+
+ function automatic [31:0] W;
+ input [6:0] x;
+ input [6:0] y;
+ if(^x === 1'bX) W = 32'h777;
+ else W = (x<16) ? padded[((PADDED_SIZE-1-y*512)-x*32) -: 32] : rho1(W(x-2, y)) + W(x-7, y) + rho0(W(x-15, y)) + W(x-16, y);
+ endfunction
+
+ function automatic [31:0] rho0;
+ input [31:0] x;
+ if(^x === 1'bX) rho0 = 32'h888;
+ else rho0 = {x[6:0],x[31:7]} ^ {x[17:0],x[31:18]} ^ (x >> 3);
+ endfunction
+
+ function automatic [31:0] rho1;
+ input [31:0] x;
+ if(^x === 1'bX) rho1 = 32'h888;
+ else rho1 = {x[16:0],x[31:17]} ^ {x[18:0],x[31:19]} ^ (x >> 10);
+ endfunction
+
+ function [31:0] ch;
+ input [31:0] x,y,z;
+ if(^x === 1'bX) ch = 32'h888;
+ else ch = (x & y) ^ (~x & z);
+ endfunction
+
+ function [31:0] maj;
+ input [31:0] x,y,z;
+ if(^x === 1'bX) maj = 32'h888;
+ else maj = (x & y) ^ (x & z) ^ (y & z);
+ endfunction
+
+ function [31:0] sum0;
+ input [31:0] x;
+ if(^x === 1'bX) sum0 = 32'h888;
+ else sum0 = {x[1:0],x[31:2]} ^ {x[12:0],x[31:13]} ^ {x[21:0],x[31:22]};
+ endfunction
+
+ function [31:0] sum1;
+ input [31:0] x;
+ if(^x === 1'bX) sum1 = 32'h888;
+ else sum1 = {x[5:0],x[31:6]} ^ {x[10:0],x[31:11]} ^ {x[24:0],x[31:25]};
+ endfunction
+
+ logic [255:0] initial_hashes = {32'h6a09e667, 32'hbb67ae85, 32'h3c6ef372, 32'ha54ff53a, 32'h510e527f, 32'h9b05688c, 32'h1f83d9ab, 32'h5be0cd19};
+
+ logic [2047:0] k = {32'h428a2f98, 32'h71374491, 32'hb5c0fbcf, 32'he9b5dba5, 32'h3956c25b, 32'h59f111f1, 32'h923f82a4, 32'hab1c5ed5, 32'hd807aa98, 32'h12835b01, 32'h243185be, 32'h550c7dc3, 32'h72be5d74, 32'h80deb1fe, 32'h9bdc06a7, 32'hc19bf174, 32'he49b69c1, 32'hefbe4786, 32'h0fc19dc6, 32'h240ca1cc, 32'h2de92c6f, 32'h4a7484aa, 32'h5cb0a9dc, 32'h76f988da, 32'h983e5152, 32'ha831c66d, 32'hb00327c8, 32'hbf597fc7, 32'hc6e00bf3, 32'hd5a79147, 32'h06ca6351, 32'h14292967, 32'h27b70a85, 32'h2e1b2138, 32'h4d2c6dfc, 32'h53380d13, 32'h650a7354, 32'h766a0abb, 32'h81c2c92e, 32'h92722c85, 32'ha2bfe8a1, 32'ha81a664b, 32'hc24b8b70, 32'hc76c51a3, 32'hd192e819, 32'hd6990624, 32'hf40e3585, 32'h106aa070, 32'h19a4c116, 32'h1e376c08, 32'h2748774c, 32'h34b0bcb5, 32'h391c0cb3, 32'h4ed8aa4a, 32'h5b9cca4f, 32'h682e6ff3, 32'h748f82ee, 32'h78a5636f, 32'h84c87814, 32'h8cc70208, 32'h90befffa, 32'ha4506ceb, 32'hbef9a3f7, 32'hc67178f2};
+
+ logic [31:0] a, b, c, d, e, f, g, h, t1, t2;
+ logic [31:0] h1, h2, h3, h4, h5, h6, h7, h8;
+
+ logic [6:0] j;
+ logic [6:0] i;
+
+ localparam N = PADDED_SIZE/512; // number of blocks
+
+ logic [31:0] ch_efg, maj_abc, sum0_a, sum1_e, kj, wj;
+
+ // (e or f or g or ch_efg)
+ always_comb begin
+ ch_efg = ch(e,f,g);
+ maj_abc = maj(a,b,c);
+ sum0_a = sum0(a);
+ sum1_e = sum1(e);
+ wj = W(j, i);
+ kj = K(j);
+ end
+
+ always @(negedge clk) begin
+ // t1 <= h + sum1(e) + ch(e,f,g) + K(j) + W(j);
+ // t2 <= sum0(a) + maj(a,b,c);
+ t1 <= (h + sum1_e + ch_efg + kj + wj)%4294967296;
+ t2 <= (sum0_a + maj_abc)%4294967296;
+ end
+
+ always @(posedge clk or posedge rst) begin
+ if(rst) begin
+ i <= 1'b0;
+ j <= 1'bX;
+ h1 <= 32'h6a09e667;
+ h2 <= 32'hbb67ae85;
+ h3 <= 32'h3c6ef372;
+ h4 <= 32'ha54ff53a;
+ h5 <= 32'h510e527f;
+ h6 <= 32'h9b05688c;
+ h7 <= 32'h1f83d9ab;
+ h8 <= 32'h5be0cd19;
+ end
+ else if (^j === 1'bX && ^i !== 1'bX) begin
+ a <= h1;
+ b <= h2;
+ c <= h3;
+ d <= h4;
+ e <= h5;
+ f <= h6;
+ g <= h7;
+ h <= h8;
+ j <= 1'd0;
+ end
+ else if (j < 64) begin
+ h <= g;
+ g <= f;
+ f <= e;
+ e <= (d+t1)%4294967296;
+ d <= c;
+ c <= b;
+ b <= a;
+ a <= (t1+t2)%4294967296;
+ j <= j+1;
+ end
+ else if (j == 64) begin
+ h1 <= a + h1;
+ h2 <= b + h2;
+ h3 <= c + h3;
+ h4 <= d + h4;
+ h5 <= e + h5;
+ h6 <= f + h6;
+ h7 <= g + h7;
+ h8 <= h + h8;
+ j <= 1'bX;
+ if (i<N-1) i <= i+1;
+ else begin
+ i <= 1'bX;
+ done <= 1'b1;
+ end
+ end
+ end
+
+ assign hashed = {h1, h2, h3, h4, h5, h6, h7, h8};
+endmodule // sha_mainloop
+
+`default_nettype wire
diff --git a/verilog/rtl/sha256.v b/verilog/rtl/sha256.v
new file mode 100644
index 0000000..3fe2a92
--- /dev/null
+++ b/verilog/rtl/sha256.v
@@ -0,0 +1,266 @@
+//======================================================================
+//
+// sha256.v
+// --------
+// Top level wrapper for the SHA-256 hash function providing
+// a simple memory like interface with 32 bit data access.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, 201, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+`default_nettype none
+
+module sha256(
+ // Clock and reset.
+ input wire clk,
+ input wire reset_n,
+
+ // Control.
+ input wire cs,
+ input wire we,
+
+ // Data ports.
+ input wire [7 : 0] address,
+ input wire [31 : 0] write_data,
+ output wire [31 : 0] read_data,
+ output wire error
+ );
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ localparam ADDR_NAME0 = 8'h00;
+ localparam ADDR_NAME1 = 8'h01;
+ localparam ADDR_VERSION = 8'h02;
+
+ localparam ADDR_CTRL = 8'h08;
+ localparam CTRL_INIT_BIT = 0;
+ localparam CTRL_NEXT_BIT = 1;
+ localparam CTRL_MODE_BIT = 2;
+
+ localparam ADDR_STATUS = 8'h09;
+ localparam STATUS_READY_BIT = 0;
+ localparam STATUS_VALID_BIT = 1;
+
+ localparam ADDR_BLOCK0 = 8'h10;
+ localparam ADDR_BLOCK15 = 8'h1f;
+
+ localparam ADDR_DIGEST0 = 8'h20;
+ localparam ADDR_DIGEST7 = 8'h27;
+
+ localparam CORE_NAME0 = 32'h73686132; // "sha2"
+ localparam CORE_NAME1 = 32'h2d323536; // "-256"
+ localparam CORE_VERSION = 32'h312e3830; // "1.80"
+
+ localparam MODE_SHA_224 = 1'h0;
+ localparam MODE_SHA_256 = 1'h1;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg init_reg;
+ reg init_new;
+
+ reg next_reg;
+ reg next_new;
+
+ reg mode_reg;
+ reg mode_new;
+ reg mode_we;
+
+ reg ready_reg;
+
+ reg [31 : 0] block_reg [0 : 15];
+ reg block_we;
+
+ reg [255 : 0] digest_reg;
+
+ reg digest_valid_reg;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ wire core_ready;
+ wire [511 : 0] core_block;
+ wire [255 : 0] core_digest;
+ wire core_digest_valid;
+
+ reg [31 : 0] tmp_read_data;
+ reg tmp_error;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign core_block = {block_reg[00], block_reg[01], block_reg[02], block_reg[03],
+ block_reg[04], block_reg[05], block_reg[06], block_reg[07],
+ block_reg[08], block_reg[09], block_reg[10], block_reg[11],
+ block_reg[12], block_reg[13], block_reg[14], block_reg[15]};
+
+ assign read_data = tmp_read_data;
+ assign error = tmp_error;
+
+
+ //----------------------------------------------------------------
+ // core instantiation.
+ //----------------------------------------------------------------
+ sha256_core core(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .init(init_reg),
+ .next(next_reg),
+ .mode(mode_reg),
+
+ .block(core_block),
+
+ .ready(core_ready),
+
+ .digest(core_digest),
+ .digest_valid(core_digest_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin : reg_update
+ integer i;
+
+ if (!reset_n)
+ begin
+ for (i = 0 ; i < 16 ; i = i + 1)
+ block_reg[i] <= 32'h0;
+
+ init_reg <= 0;
+ next_reg <= 0;
+ ready_reg <= 0;
+ mode_reg <= MODE_SHA_256;
+ digest_reg <= 256'h0;
+ digest_valid_reg <= 0;
+ end
+ else
+ begin
+ ready_reg <= core_ready;
+ digest_valid_reg <= core_digest_valid;
+ init_reg <= init_new;
+ next_reg <= next_new;
+
+ if (mode_we)
+ mode_reg <= mode_new;
+
+ if (core_digest_valid)
+ digest_reg <= core_digest;
+
+ if (block_we)
+ block_reg[address[3 : 0]] <= write_data;
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // api_logic
+ //
+ // Implementation of the api logic. If cs is enabled will either
+ // try to write to or read from the internal registers.
+ //----------------------------------------------------------------
+ always @*
+ begin : api_logic
+ init_new = 0;
+ next_new = 0;
+ mode_new = 0;
+ mode_we = 0;
+ block_we = 0;
+ tmp_read_data = 32'h0;
+ tmp_error = 0;
+
+ if (cs)
+ begin
+ if (we)
+ begin
+ if (address == ADDR_CTRL)
+ begin
+ init_new = write_data[CTRL_INIT_BIT];
+ next_new = write_data[CTRL_NEXT_BIT];
+ mode_new = write_data[CTRL_MODE_BIT];
+ mode_we = 1;
+ end
+
+ if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK15))
+ block_we = 1;
+ end // if (we)
+
+ else
+ begin
+ // read
+ if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK15))
+ tmp_read_data = block_reg[address[3 : 0]];
+
+ if ((address >= ADDR_DIGEST0) && (address <= ADDR_DIGEST7))
+ tmp_read_data = digest_reg[(7 - (address - ADDR_DIGEST0)) * 32 +: 32];
+
+ case (address)
+ // Read operations.
+ ADDR_NAME0:
+ tmp_read_data = CORE_NAME0;
+
+ ADDR_NAME1:
+ tmp_read_data = CORE_NAME1;
+
+ ADDR_VERSION:
+ tmp_read_data = CORE_VERSION;
+
+ ADDR_CTRL:
+ tmp_read_data = {29'h0, mode_reg, next_reg, init_reg};
+
+ ADDR_STATUS:
+ tmp_read_data = {30'h0, digest_valid_reg, ready_reg};
+
+ default:
+ begin
+ end
+ endcase // case (address)
+ end
+ end
+ end // addr_decoder
+endmodule // sha256
+
+//======================================================================
+// EOF sha256.v
+//======================================================================
diff --git a/verilog/rtl/sha256_core.v b/verilog/rtl/sha256_core.v
new file mode 100644
index 0000000..b2c880e
--- /dev/null
+++ b/verilog/rtl/sha256_core.v
@@ -0,0 +1,552 @@
+//======================================================================
+//
+// sha256_core.v
+// -------------
+// Verilog 2001 implementation of the SHA-256 hash function.
+// This is the internal core with wide interfaces.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+`default_nettype none
+
+module sha256_core(
+ input wire clk,
+ input wire reset_n,
+
+ input wire init,
+ input wire next,
+ input wire mode,
+
+ input wire [511 : 0] block,
+
+ output wire ready,
+ output wire [255 : 0] digest,
+ output wire digest_valid
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ localparam SHA224_H0_0 = 32'hc1059ed8;
+ localparam SHA224_H0_1 = 32'h367cd507;
+ localparam SHA224_H0_2 = 32'h3070dd17;
+ localparam SHA224_H0_3 = 32'hf70e5939;
+ localparam SHA224_H0_4 = 32'hffc00b31;
+ localparam SHA224_H0_5 = 32'h68581511;
+ localparam SHA224_H0_6 = 32'h64f98fa7;
+ localparam SHA224_H0_7 = 32'hbefa4fa4;
+
+ localparam SHA256_H0_0 = 32'h6a09e667;
+ localparam SHA256_H0_1 = 32'hbb67ae85;
+ localparam SHA256_H0_2 = 32'h3c6ef372;
+ localparam SHA256_H0_3 = 32'ha54ff53a;
+ localparam SHA256_H0_4 = 32'h510e527f;
+ localparam SHA256_H0_5 = 32'h9b05688c;
+ localparam SHA256_H0_6 = 32'h1f83d9ab;
+ localparam SHA256_H0_7 = 32'h5be0cd19;
+
+ localparam SHA256_ROUNDS = 63;
+
+ localparam CTRL_IDLE = 0;
+ localparam CTRL_ROUNDS = 1;
+ localparam CTRL_DONE = 2;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [31 : 0] a_reg;
+ reg [31 : 0] a_new;
+ reg [31 : 0] b_reg;
+ reg [31 : 0] b_new;
+ reg [31 : 0] c_reg;
+ reg [31 : 0] c_new;
+ reg [31 : 0] d_reg;
+ reg [31 : 0] d_new;
+ reg [31 : 0] e_reg;
+ reg [31 : 0] e_new;
+ reg [31 : 0] f_reg;
+ reg [31 : 0] f_new;
+ reg [31 : 0] g_reg;
+ reg [31 : 0] g_new;
+ reg [31 : 0] h_reg;
+ reg [31 : 0] h_new;
+ reg a_h_we;
+
+ reg [31 : 0] H0_reg;
+ reg [31 : 0] H0_new;
+ reg [31 : 0] H1_reg;
+ reg [31 : 0] H1_new;
+ reg [31 : 0] H2_reg;
+ reg [31 : 0] H2_new;
+ reg [31 : 0] H3_reg;
+ reg [31 : 0] H3_new;
+ reg [31 : 0] H4_reg;
+ reg [31 : 0] H4_new;
+ reg [31 : 0] H5_reg;
+ reg [31 : 0] H5_new;
+ reg [31 : 0] H6_reg;
+ reg [31 : 0] H6_new;
+ reg [31 : 0] H7_reg;
+ reg [31 : 0] H7_new;
+ reg H_we;
+
+ reg [5 : 0] t_ctr_reg;
+ reg [5 : 0] t_ctr_new;
+ reg t_ctr_we;
+ reg t_ctr_inc;
+ reg t_ctr_rst;
+
+ reg digest_valid_reg;
+ reg digest_valid_new;
+ reg digest_valid_we;
+
+ reg [1 : 0] sha256_ctrl_reg;
+ reg [1 : 0] sha256_ctrl_new;
+ reg sha256_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg digest_init;
+ reg digest_update;
+
+ reg state_init;
+ reg state_update;
+
+ reg first_block;
+
+ reg ready_flag;
+
+ reg [31 : 0] t1;
+ reg [31 : 0] t2;
+
+ wire [31 : 0] k_data;
+
+ reg w_init;
+ reg w_next;
+ wire [31 : 0] w_data;
+
+
+ //----------------------------------------------------------------
+ // Module instantiantions.
+ //----------------------------------------------------------------
+ sha256_k_constants k_constants_inst(
+ .round(t_ctr_reg),
+ .K(k_data)
+ );
+
+
+ sha256_w_mem w_mem_inst(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .block(block),
+
+ .init(w_init),
+ .next(w_next),
+ .w(w_data)
+ );
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign ready = ready_flag;
+
+ assign digest = {H0_reg, H1_reg, H2_reg, H3_reg,
+ H4_reg, H5_reg, H6_reg, H7_reg};
+
+ assign digest_valid = digest_valid_reg;
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin : reg_update
+ if (!reset_n)
+ begin
+ a_reg <= 32'h0;
+ b_reg <= 32'h0;
+ c_reg <= 32'h0;
+ d_reg <= 32'h0;
+ e_reg <= 32'h0;
+ f_reg <= 32'h0;
+ g_reg <= 32'h0;
+ h_reg <= 32'h0;
+ H0_reg <= 32'h0;
+ H1_reg <= 32'h0;
+ H2_reg <= 32'h0;
+ H3_reg <= 32'h0;
+ H4_reg <= 32'h0;
+ H5_reg <= 32'h0;
+ H6_reg <= 32'h0;
+ H7_reg <= 32'h0;
+ digest_valid_reg <= 0;
+ t_ctr_reg <= 6'h0;
+ sha256_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+
+ if (a_h_we)
+ begin
+ a_reg <= a_new;
+ b_reg <= b_new;
+ c_reg <= c_new;
+ d_reg <= d_new;
+ e_reg <= e_new;
+ f_reg <= f_new;
+ g_reg <= g_new;
+ h_reg <= h_new;
+ end
+
+ if (H_we)
+ begin
+ H0_reg <= H0_new;
+ H1_reg <= H1_new;
+ H2_reg <= H2_new;
+ H3_reg <= H3_new;
+ H4_reg <= H4_new;
+ H5_reg <= H5_new;
+ H6_reg <= H6_new;
+ H7_reg <= H7_new;
+ end
+
+ if (t_ctr_we)
+ t_ctr_reg <= t_ctr_new;
+
+ if (digest_valid_we)
+ digest_valid_reg <= digest_valid_new;
+
+ if (sha256_ctrl_we)
+ sha256_ctrl_reg <= sha256_ctrl_new;
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // digest_logic
+ //
+ // The logic needed to init as well as update the digest.
+ //----------------------------------------------------------------
+ always @*
+ begin : digest_logic
+ H0_new = 32'h0;
+ H1_new = 32'h0;
+ H2_new = 32'h0;
+ H3_new = 32'h0;
+ H4_new = 32'h0;
+ H5_new = 32'h0;
+ H6_new = 32'h0;
+ H7_new = 32'h0;
+ H_we = 0;
+
+ if (digest_init)
+ begin
+ H_we = 1;
+ if (mode)
+ begin
+ H0_new = SHA256_H0_0;
+ H1_new = SHA256_H0_1;
+ H2_new = SHA256_H0_2;
+ H3_new = SHA256_H0_3;
+ H4_new = SHA256_H0_4;
+ H5_new = SHA256_H0_5;
+ H6_new = SHA256_H0_6;
+ H7_new = SHA256_H0_7;
+ end
+ else
+ begin
+ H0_new = SHA224_H0_0;
+ H1_new = SHA224_H0_1;
+ H2_new = SHA224_H0_2;
+ H3_new = SHA224_H0_3;
+ H4_new = SHA224_H0_4;
+ H5_new = SHA224_H0_5;
+ H6_new = SHA224_H0_6;
+ H7_new = SHA224_H0_7;
+ end
+ end
+
+ if (digest_update)
+ begin
+ H0_new = H0_reg + a_reg;
+ H1_new = H1_reg + b_reg;
+ H2_new = H2_reg + c_reg;
+ H3_new = H3_reg + d_reg;
+ H4_new = H4_reg + e_reg;
+ H5_new = H5_reg + f_reg;
+ H6_new = H6_reg + g_reg;
+ H7_new = H7_reg + h_reg;
+ H_we = 1;
+ end
+ end // digest_logic
+
+
+ //----------------------------------------------------------------
+ // t1_logic
+ //
+ // The logic for the T1 function.
+ //----------------------------------------------------------------
+ always @*
+ begin : t1_logic
+ reg [31 : 0] sum1;
+ reg [31 : 0] ch;
+
+ sum1 = {e_reg[5 : 0], e_reg[31 : 6]} ^
+ {e_reg[10 : 0], e_reg[31 : 11]} ^
+ {e_reg[24 : 0], e_reg[31 : 25]};
+
+ ch = (e_reg & f_reg) ^ ((~e_reg) & g_reg);
+
+ t1 = h_reg + sum1 + ch + w_data + k_data;
+ end // t1_logic
+
+
+ //----------------------------------------------------------------
+ // t2_logic
+ //
+ // The logic for the T2 function
+ //----------------------------------------------------------------
+ always @*
+ begin : t2_logic
+ reg [31 : 0] sum0;
+ reg [31 : 0] maj;
+
+ sum0 = {a_reg[1 : 0], a_reg[31 : 2]} ^
+ {a_reg[12 : 0], a_reg[31 : 13]} ^
+ {a_reg[21 : 0], a_reg[31 : 22]};
+
+ maj = (a_reg & b_reg) ^ (a_reg & c_reg) ^ (b_reg & c_reg);
+
+ t2 = sum0 + maj;
+ end // t2_logic
+
+
+ //----------------------------------------------------------------
+ // state_logic
+ //
+ // The logic needed to init as well as update the state during
+ // round processing.
+ //----------------------------------------------------------------
+ always @*
+ begin : state_logic
+ a_new = 32'h0;
+ b_new = 32'h0;
+ c_new = 32'h0;
+ d_new = 32'h0;
+ e_new = 32'h0;
+ f_new = 32'h0;
+ g_new = 32'h0;
+ h_new = 32'h0;
+ a_h_we = 0;
+
+ if (state_init)
+ begin
+ a_h_we = 1;
+ if (first_block)
+ begin
+ if (mode)
+ begin
+ a_new = SHA256_H0_0;
+ b_new = SHA256_H0_1;
+ c_new = SHA256_H0_2;
+ d_new = SHA256_H0_3;
+ e_new = SHA256_H0_4;
+ f_new = SHA256_H0_5;
+ g_new = SHA256_H0_6;
+ h_new = SHA256_H0_7;
+ end
+ else
+ begin
+ a_new = SHA224_H0_0;
+ b_new = SHA224_H0_1;
+ c_new = SHA224_H0_2;
+ d_new = SHA224_H0_3;
+ e_new = SHA224_H0_4;
+ f_new = SHA224_H0_5;
+ g_new = SHA224_H0_6;
+ h_new = SHA224_H0_7;
+ end
+ end
+ else
+ begin
+ a_new = H0_reg;
+ b_new = H1_reg;
+ c_new = H2_reg;
+ d_new = H3_reg;
+ e_new = H4_reg;
+ f_new = H5_reg;
+ g_new = H6_reg;
+ h_new = H7_reg;
+ end
+ end
+
+ if (state_update)
+ begin
+ a_new = t1 + t2;
+ b_new = a_reg;
+ c_new = b_reg;
+ d_new = c_reg;
+ e_new = d_reg + t1;
+ f_new = e_reg;
+ g_new = f_reg;
+ h_new = g_reg;
+ a_h_we = 1;
+ end
+ end // state_logic
+
+
+ //----------------------------------------------------------------
+ // t_ctr
+ //
+ // Update logic for the round counter, a monotonically
+ // increasing counter with reset.
+ //----------------------------------------------------------------
+ always @*
+ begin : t_ctr
+ t_ctr_new = 0;
+ t_ctr_we = 0;
+
+ if (t_ctr_rst)
+ begin
+ t_ctr_new = 0;
+ t_ctr_we = 1;
+ end
+
+ if (t_ctr_inc)
+ begin
+ t_ctr_new = t_ctr_reg + 1'b1;
+ t_ctr_we = 1;
+ end
+ end // t_ctr
+
+
+ //----------------------------------------------------------------
+ // sha256_ctrl_fsm
+ //
+ // Logic for the state machine controlling the core behaviour.
+ //----------------------------------------------------------------
+ always @*
+ begin : sha256_ctrl_fsm
+ digest_init = 0;
+ digest_update = 0;
+
+ state_init = 0;
+ state_update = 0;
+
+ first_block = 0;
+ ready_flag = 0;
+
+ w_init = 0;
+ w_next = 0;
+
+ t_ctr_inc = 0;
+ t_ctr_rst = 0;
+
+ digest_valid_new = 0;
+ digest_valid_we = 0;
+
+ sha256_ctrl_new = CTRL_IDLE;
+ sha256_ctrl_we = 0;
+
+
+ case (sha256_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ ready_flag = 1;
+
+ if (init)
+ begin
+ digest_init = 1;
+ w_init = 1;
+ state_init = 1;
+ first_block = 1;
+ t_ctr_rst = 1;
+ digest_valid_new = 0;
+ digest_valid_we = 1;
+ sha256_ctrl_new = CTRL_ROUNDS;
+ sha256_ctrl_we = 1;
+ end
+
+ if (next)
+ begin
+ t_ctr_rst = 1;
+ w_init = 1;
+ state_init = 1;
+ digest_valid_new = 0;
+ digest_valid_we = 1;
+ sha256_ctrl_new = CTRL_ROUNDS;
+ sha256_ctrl_we = 1;
+ end
+ end
+
+
+ CTRL_ROUNDS:
+ begin
+ w_next = 1;
+ state_update = 1;
+ t_ctr_inc = 1;
+
+ if (t_ctr_reg == SHA256_ROUNDS)
+ begin
+ sha256_ctrl_new = CTRL_DONE;
+ sha256_ctrl_we = 1;
+ end
+ end
+
+
+ CTRL_DONE:
+ begin
+ digest_update = 1;
+ digest_valid_new = 1;
+ digest_valid_we = 1;
+
+ sha256_ctrl_new = CTRL_IDLE;
+ sha256_ctrl_we = 1;
+ end
+ endcase // case (sha256_ctrl_reg)
+ end // sha256_ctrl_fsm
+
+endmodule // sha256_core
+
+//======================================================================
+// EOF sha256_core.v
+//======================================================================
diff --git a/verilog/rtl/sha256_k_constants.v b/verilog/rtl/sha256_k_constants.v
new file mode 100644
index 0000000..bae748e
--- /dev/null
+++ b/verilog/rtl/sha256_k_constants.v
@@ -0,0 +1,134 @@
+//======================================================================
+//
+// sha256_k_constants.v
+// --------------------
+// The table K with constants in the SHA-256 hash function.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+`default_nettype none
+
+module sha256_k_constants(
+ input wire [5 : 0] round,
+ output wire [31 : 0] K
+ );
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] tmp_K;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign K = tmp_K;
+
+
+ //----------------------------------------------------------------
+ // round_mux
+ //----------------------------------------------------------------
+ always @*
+ begin : round_mux
+ case(round)
+ 00: tmp_K = 32'h428a2f98;
+ 01: tmp_K = 32'h71374491;
+ 02: tmp_K = 32'hb5c0fbcf;
+ 03: tmp_K = 32'he9b5dba5;
+ 04: tmp_K = 32'h3956c25b;
+ 05: tmp_K = 32'h59f111f1;
+ 06: tmp_K = 32'h923f82a4;
+ 07: tmp_K = 32'hab1c5ed5;
+ 08: tmp_K = 32'hd807aa98;
+ 09: tmp_K = 32'h12835b01;
+ 10: tmp_K = 32'h243185be;
+ 11: tmp_K = 32'h550c7dc3;
+ 12: tmp_K = 32'h72be5d74;
+ 13: tmp_K = 32'h80deb1fe;
+ 14: tmp_K = 32'h9bdc06a7;
+ 15: tmp_K = 32'hc19bf174;
+ 16: tmp_K = 32'he49b69c1;
+ 17: tmp_K = 32'hefbe4786;
+ 18: tmp_K = 32'h0fc19dc6;
+ 19: tmp_K = 32'h240ca1cc;
+ 20: tmp_K = 32'h2de92c6f;
+ 21: tmp_K = 32'h4a7484aa;
+ 22: tmp_K = 32'h5cb0a9dc;
+ 23: tmp_K = 32'h76f988da;
+ 24: tmp_K = 32'h983e5152;
+ 25: tmp_K = 32'ha831c66d;
+ 26: tmp_K = 32'hb00327c8;
+ 27: tmp_K = 32'hbf597fc7;
+ 28: tmp_K = 32'hc6e00bf3;
+ 29: tmp_K = 32'hd5a79147;
+ 30: tmp_K = 32'h06ca6351;
+ 31: tmp_K = 32'h14292967;
+ 32: tmp_K = 32'h27b70a85;
+ 33: tmp_K = 32'h2e1b2138;
+ 34: tmp_K = 32'h4d2c6dfc;
+ 35: tmp_K = 32'h53380d13;
+ 36: tmp_K = 32'h650a7354;
+ 37: tmp_K = 32'h766a0abb;
+ 38: tmp_K = 32'h81c2c92e;
+ 39: tmp_K = 32'h92722c85;
+ 40: tmp_K = 32'ha2bfe8a1;
+ 41: tmp_K = 32'ha81a664b;
+ 42: tmp_K = 32'hc24b8b70;
+ 43: tmp_K = 32'hc76c51a3;
+ 44: tmp_K = 32'hd192e819;
+ 45: tmp_K = 32'hd6990624;
+ 46: tmp_K = 32'hf40e3585;
+ 47: tmp_K = 32'h106aa070;
+ 48: tmp_K = 32'h19a4c116;
+ 49: tmp_K = 32'h1e376c08;
+ 50: tmp_K = 32'h2748774c;
+ 51: tmp_K = 32'h34b0bcb5;
+ 52: tmp_K = 32'h391c0cb3;
+ 53: tmp_K = 32'h4ed8aa4a;
+ 54: tmp_K = 32'h5b9cca4f;
+ 55: tmp_K = 32'h682e6ff3;
+ 56: tmp_K = 32'h748f82ee;
+ 57: tmp_K = 32'h78a5636f;
+ 58: tmp_K = 32'h84c87814;
+ 59: tmp_K = 32'h8cc70208;
+ 60: tmp_K = 32'h90befffa;
+ 61: tmp_K = 32'ha4506ceb;
+ 62: tmp_K = 32'hbef9a3f7;
+ 63: tmp_K = 32'hc67178f2;
+ endcase // case (round)
+ end // block: round_mux
+endmodule // sha256_k_constants
+
+//======================================================================
+// sha256_k_constants.v
+//======================================================================
diff --git a/verilog/rtl/sha256_w_mem.v b/verilog/rtl/sha256_w_mem.v
new file mode 100644
index 0000000..06f4d46
--- /dev/null
+++ b/verilog/rtl/sha256_w_mem.v
@@ -0,0 +1,272 @@
+//======================================================================
+//
+// sha256_w_mem_regs.v
+// -------------------
+// The W memory. This version uses 16 32-bit registers as a sliding
+// window to generate the 64 words.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+`default_nettype none
+
+module sha256_w_mem(
+ input wire clk,
+ input wire reset_n,
+
+ input wire [511 : 0] block,
+
+ input wire init,
+ input wire next,
+ output wire [31 : 0] w
+ );
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [31 : 0] w_mem [0 : 15];
+ reg [31 : 0] w_mem00_new;
+ reg [31 : 0] w_mem01_new;
+ reg [31 : 0] w_mem02_new;
+ reg [31 : 0] w_mem03_new;
+ reg [31 : 0] w_mem04_new;
+ reg [31 : 0] w_mem05_new;
+ reg [31 : 0] w_mem06_new;
+ reg [31 : 0] w_mem07_new;
+ reg [31 : 0] w_mem08_new;
+ reg [31 : 0] w_mem09_new;
+ reg [31 : 0] w_mem10_new;
+ reg [31 : 0] w_mem11_new;
+ reg [31 : 0] w_mem12_new;
+ reg [31 : 0] w_mem13_new;
+ reg [31 : 0] w_mem14_new;
+ reg [31 : 0] w_mem15_new;
+ reg w_mem_we;
+
+ reg [5 : 0] w_ctr_reg;
+ reg [5 : 0] w_ctr_new;
+ reg w_ctr_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] w_tmp;
+ reg [31 : 0] w_new;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign w = w_tmp;
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with synchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin : reg_update
+ integer i;
+
+ if (!reset_n)
+ begin
+ for (i = 0 ; i < 16 ; i = i + 1)
+ w_mem[i] <= 32'h0;
+
+ w_ctr_reg <= 6'h0;
+ end
+ else
+ begin
+ if (w_mem_we)
+ begin
+ w_mem[00] <= w_mem00_new;
+ w_mem[01] <= w_mem01_new;
+ w_mem[02] <= w_mem02_new;
+ w_mem[03] <= w_mem03_new;
+ w_mem[04] <= w_mem04_new;
+ w_mem[05] <= w_mem05_new;
+ w_mem[06] <= w_mem06_new;
+ w_mem[07] <= w_mem07_new;
+ w_mem[08] <= w_mem08_new;
+ w_mem[09] <= w_mem09_new;
+ w_mem[10] <= w_mem10_new;
+ w_mem[11] <= w_mem11_new;
+ w_mem[12] <= w_mem12_new;
+ w_mem[13] <= w_mem13_new;
+ w_mem[14] <= w_mem14_new;
+ w_mem[15] <= w_mem15_new;
+ end
+
+ if (w_ctr_we)
+ w_ctr_reg <= w_ctr_new;
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // select_w
+ //
+ // Mux for the external read operation. This is where we exract
+ // the W variable.
+ //----------------------------------------------------------------
+ always @*
+ begin : select_w
+ if (w_ctr_reg < 16)
+ w_tmp = w_mem[w_ctr_reg[3 : 0]];
+ else
+ w_tmp = w_new;
+ end // select_w
+
+
+ //----------------------------------------------------------------
+ // w_new_logic
+ //
+ // Logic that calculates the next value to be inserted into
+ // the sliding window of the memory.
+ //----------------------------------------------------------------
+ always @*
+ begin : w_mem_update_logic
+ reg [31 : 0] w_0;
+ reg [31 : 0] w_1;
+ reg [31 : 0] w_9;
+ reg [31 : 0] w_14;
+ reg [31 : 0] d0;
+ reg [31 : 0] d1;
+
+ w_mem00_new = 32'h0;
+ w_mem01_new = 32'h0;
+ w_mem02_new = 32'h0;
+ w_mem03_new = 32'h0;
+ w_mem04_new = 32'h0;
+ w_mem05_new = 32'h0;
+ w_mem06_new = 32'h0;
+ w_mem07_new = 32'h0;
+ w_mem08_new = 32'h0;
+ w_mem09_new = 32'h0;
+ w_mem10_new = 32'h0;
+ w_mem11_new = 32'h0;
+ w_mem12_new = 32'h0;
+ w_mem13_new = 32'h0;
+ w_mem14_new = 32'h0;
+ w_mem15_new = 32'h0;
+ w_mem_we = 0;
+
+ w_0 = w_mem[0];
+ w_1 = w_mem[1];
+ w_9 = w_mem[9];
+ w_14 = w_mem[14];
+
+ d0 = {w_1[6 : 0], w_1[31 : 7]} ^
+ {w_1[17 : 0], w_1[31 : 18]} ^
+ {3'b000, w_1[31 : 3]};
+
+ d1 = {w_14[16 : 0], w_14[31 : 17]} ^
+ {w_14[18 : 0], w_14[31 : 19]} ^
+ {10'b0000000000, w_14[31 : 10]};
+
+ w_new = d1 + w_9 + d0 + w_0;
+
+ if (init)
+ begin
+ w_mem00_new = block[511 : 480];
+ w_mem01_new = block[479 : 448];
+ w_mem02_new = block[447 : 416];
+ w_mem03_new = block[415 : 384];
+ w_mem04_new = block[383 : 352];
+ w_mem05_new = block[351 : 320];
+ w_mem06_new = block[319 : 288];
+ w_mem07_new = block[287 : 256];
+ w_mem08_new = block[255 : 224];
+ w_mem09_new = block[223 : 192];
+ w_mem10_new = block[191 : 160];
+ w_mem11_new = block[159 : 128];
+ w_mem12_new = block[127 : 96];
+ w_mem13_new = block[95 : 64];
+ w_mem14_new = block[63 : 32];
+ w_mem15_new = block[31 : 0];
+ w_mem_we = 1;
+ end
+
+ if (next && (w_ctr_reg > 15))
+ begin
+ w_mem00_new = w_mem[01];
+ w_mem01_new = w_mem[02];
+ w_mem02_new = w_mem[03];
+ w_mem03_new = w_mem[04];
+ w_mem04_new = w_mem[05];
+ w_mem05_new = w_mem[06];
+ w_mem06_new = w_mem[07];
+ w_mem07_new = w_mem[08];
+ w_mem08_new = w_mem[09];
+ w_mem09_new = w_mem[10];
+ w_mem10_new = w_mem[11];
+ w_mem11_new = w_mem[12];
+ w_mem12_new = w_mem[13];
+ w_mem13_new = w_mem[14];
+ w_mem14_new = w_mem[15];
+ w_mem15_new = w_new;
+ w_mem_we = 1;
+ end
+ end // w_mem_update_logic
+
+
+ //----------------------------------------------------------------
+ // w_ctr
+ // W schedule adress counter. Counts from 0x10 to 0x3f and
+ // is used to expand the block into words.
+ //----------------------------------------------------------------
+ always @*
+ begin : w_ctr
+ w_ctr_new = 6'h0;
+ w_ctr_we = 1'h0;
+
+ if (init)
+ begin
+ w_ctr_new = 6'h0;
+ w_ctr_we = 1'h1;
+ end
+
+ if (next)
+ begin
+ w_ctr_new = w_ctr_reg + 6'h01;
+ w_ctr_we = 1'h1;
+ end
+ end // w_ctr
+endmodule // sha256_w_mem
+
+//======================================================================
+// sha256_w_mem.v
+//======================================================================