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
+//======================================================================