diff --git a/ip_cores/fifo/src/rtl/axi_stream_fifo.sv b/ip_cores/fifo/src/rtl/axi_stream_fifo.sv index 18922e6..d2bdd46 100644 --- a/ip_cores/fifo/src/rtl/axi_stream_fifo.sv +++ b/ip_cores/fifo/src/rtl/axi_stream_fifo.sv @@ -23,7 +23,8 @@ module axi_stream_fifo #( parameter SIZE, parameter DAT_BITS, parameter MOD_BITS = $clog2(DAT_BITS/8), - parameter CTL_BITS + parameter CTL_BITS, + parameter USE_BRAM = 0 // If using BRAM there is an extra cycle delay between reads ) ( input i_clk, i_rst, if_axi_stream.sink i_axi, @@ -33,26 +34,74 @@ module axi_stream_fifo #( ); logic [$clog2(SIZE)-1:0] rd_ptr, wr_ptr; +localparam RAM_WIDTH = DAT_BITS + CTL_BITS + MOD_BITS + 3; +logic [RAM_WIDTH-1:0] data_out; -logic [SIZE-1:0][DAT_BITS + CTL_BITS + MOD_BITS + 3 -1:0] ram; +generate + if (USE_BRAM == 0) begin: BRAM_GEN + + logic [SIZE-1:0][DAT_BITS + CTL_BITS + MOD_BITS + 3 -1:0] ram; + + always_ff @ (posedge i_clk) begin + if (i_axi.val && i_axi.rdy) begin + ram [wr_ptr] <= {i_axi.err, i_axi.eop, i_axi.sop, i_axi.mod, i_axi.ctl, i_axi.dat}; + end + end + + always_comb begin + data_out = ram [rd_ptr]; + o_axi.val = ~o_emp; + end + + end else begin + + if_ram #(.RAM_WIDTH(RAM_WIDTH), .RAM_DEPTH(SIZE)) bram_if_rd (i_clk, i_rst); + if_ram #(.RAM_WIDTH(RAM_WIDTH), .RAM_DEPTH(SIZE)) bram_if_wr (i_clk, i_rst); + + bram #( + .RAM_WIDTH ( RAM_WIDTH ), + .RAM_DEPTH ( SIZE ), + .RAM_PERFORMANCE ( "LOW_LATENCY" ) + ) bram_i ( + .a ( bram_if_rd ), + .b ( bram_if_wr ) + ); + + always_ff @ (posedge i_clk) begin + o_axi.val <= 0; + if (~o_emp) o_axi.val <= 1; + if (o_axi.val && o_axi.rdy) o_axi.val <= 0; + end + + always_comb begin + bram_if_rd.re = 1; + bram_if_rd.a = rd_ptr; + bram_if_rd.d = 0; + bram_if_rd.we = 0; + bram_if_rd.en = 1; + + bram_if_wr.re = 0; + bram_if_wr.a = wr_ptr; + bram_if_wr.d = {i_axi.err, i_axi.eop, i_axi.sop, i_axi.mod, i_axi.ctl, i_axi.dat}; + bram_if_wr.we = i_axi.val && i_axi.rdy; + bram_if_wr.en = 1; + + data_out = bram_if_rd.q; + end + end +endgenerate // Control for full and empty, and assigning outputs from the ram always_comb begin i_axi.rdy = ~o_full; - o_axi.dat = ram[rd_ptr][0 +: DAT_BITS]; - o_axi.ctl = ram[rd_ptr][DAT_BITS +: CTL_BITS]; - o_axi.mod = ram[rd_ptr][CTL_BITS+DAT_BITS +: MOD_BITS]; - o_axi.sop = ram[rd_ptr][CTL_BITS+DAT_BITS+MOD_BITS +: 1]; - o_axi.eop = ram[rd_ptr][CTL_BITS+DAT_BITS+MOD_BITS+1 +: 1]; - o_axi.err = ram[rd_ptr][CTL_BITS+DAT_BITS+MOD_BITS+2 +: 1]; - o_axi.val = ~o_emp; -end + + o_axi.dat = data_out[0 +: DAT_BITS]; + o_axi.ctl = data_out[DAT_BITS +: CTL_BITS]; + o_axi.mod = data_out[CTL_BITS+DAT_BITS +: MOD_BITS]; + o_axi.sop = data_out[CTL_BITS+DAT_BITS+MOD_BITS +: 1]; + o_axi.eop = data_out[CTL_BITS+DAT_BITS+MOD_BITS+1 +: 1]; + o_axi.err = data_out[CTL_BITS+DAT_BITS+MOD_BITS+2 +: 1]; -// Logic for writing and reading from ram without reset -always_ff @ (posedge i_clk) begin - if (i_axi.val && i_axi.rdy) begin - ram [wr_ptr] <= {i_axi.err, i_axi.eop, i_axi.sop, i_axi.mod, i_axi.ctl, i_axi.dat}; - end end // Control logic which requires a reset diff --git a/ip_cores/hash_map/src/rtl/hash_map.sv b/ip_cores/hash_map/src/rtl/hash_map.sv index a6ccfc3..e53e939 100644 --- a/ip_cores/hash_map/src/rtl/hash_map.sv +++ b/ip_cores/hash_map/src/rtl/hash_map.sv @@ -37,7 +37,8 @@ module hash_map #( output logic o_val, output logic o_fnd, // Will be high if adding a key and it already exists (old data overwritten) // or for a lookup if key was found. - + + // Configuration (overrides other signals) // To clear memory input i_cfg_clr, // When linked list memory is full this will be high @@ -162,9 +163,6 @@ always_ff @ (posedge i_clk) begin o_rdy <= 0; hash_state <= STATE_LOOPUP_COL; coll_ram_wait[0] <= 1; - end else if (i_cfg_clr) begin - o_rdy <= 0; - hash_state <= STATE_RESET; end end STATE_LOOPUP_COL: begin @@ -400,6 +398,12 @@ always_ff @ (posedge i_clk) begin end end endcase + + // Clear signal overrides others + if (i_cfg_clr) begin + o_rdy <= 0; + hash_state <= STATE_RESET; + end end end @@ -432,7 +436,8 @@ axi_stream_fifo #( .SIZE ( LL_MEM_SIZE ), .DAT_BITS ( $clog2(LL_MEM_SIZE) ), .MOD_BITS ( 1 ), - .CTL_BITS ( 1 ) + .CTL_BITS ( 1 ), + .USE_BRAM ( 1 ) ) free_mem_fifo ( .i_clk ( i_clk ), diff --git a/ip_cores/memory/rtl/src/bram.sv b/ip_cores/memory/rtl/src/bram.sv index 2b969f5..cd9b2e0 100644 --- a/ip_cores/memory/rtl/src/bram.sv +++ b/ip_cores/memory/rtl/src/bram.sv @@ -15,29 +15,37 @@ module bram #( if_ram.sink a, if_ram.sink b ); - - xilinx_true_dual_port_no_change_2_clock_ram #( - .RAM_WIDTH(RAM_WIDTH), // Specify RAM data width - .RAM_DEPTH(RAM_DEPTH), // Specify RAM depth (number of entries) - .RAM_PERFORMANCE(RAM_PERFORMANCE), // Select "HIGH_PERFORMANCE" or "LOW_LATENCY" - .INIT_FILE(INIT_FILE) // Specify name/location of RAM initialization file if using one (leave blank if not) - ) your_instance_name ( - .addra(a.a), // Port A address bus, width determined from RAM_DEPTH - .addrb(b.a), // Port B address bus, width determined from RAM_DEPTH - .dina(a.d), // Port A RAM input data, width determined from RAM_WIDTH - .dinb(b.d), // Port B RAM input data, width determined from RAM_WIDTH - .clka(a.i_clk), // Port A clock - .clkb(b.i_clk), // Port B clock - .wea(a.we), // Port A write enable - .web(b.we), // Port B write enable - .ena(a.en), // Port A RAM Enable, for additional power savings, disable port when not in use - .enb(b.en), // Port B RAM Enable, for additional power savings, disable port when not in use - .rsta(a.i_rst), // Port A output reset (does not affect memory contents) - .rstb(b.i_rst), // Port B output reset (does not affect memory contents) - .regcea(a.re), // Port A output register enable - .regceb(b.re), // Port B output register enable - .douta(a.q), // Port A RAM output data, width determined from RAM_WIDTH - .doutb(b.q) // Port B RAM output data, width determined from RAM_WIDTH + + // Check RAM sizes match the interface + initial begin + assert ($bits(a.d) == RAM_WIDTH) else $fatal(1, "%m %t ERROR: bram RAM_WIDTH (%d) does not match interface a (%d)", $time, RAM_WIDTH, $bits(a.d)); + assert ($bits(a.a) == $clog2(RAM_DEPTH)) else $fatal(1, "%m %t ERROR: bram $clog2(RAM_DEPTH) (%d) does not match interface a (%d)", $time, $clog2(RAM_DEPTH), $bits(a.a)); + assert ($bits(b.d) == RAM_WIDTH) else $fatal(1, "%m %t ERROR: bram RAM_WIDTH (%d) does not match interface b (%d)", $time, RAM_WIDTH, $bits(b.d)); + assert ($bits(b.a) == $clog2(RAM_DEPTH)) else $fatal(1, "%m %t ERROR: bram $clog2(RAM_DEPTH) (%d) does not match interface b (%d)", $time, $clog2(RAM_DEPTH), $bits(b.a)); + end + + xilinx_true_dual_port_no_change_2_clock_ram #( + .RAM_WIDTH(RAM_WIDTH), // Specify RAM data width + .RAM_DEPTH(RAM_DEPTH), // Specify RAM depth (number of entries) + .RAM_PERFORMANCE(RAM_PERFORMANCE), // Select "HIGH_PERFORMANCE" or "LOW_LATENCY" + .INIT_FILE(INIT_FILE) // Specify name/location of RAM initialization file if using one (leave blank if not) + ) your_instance_name ( + .addra(a.a), // Port A address bus, width determined from RAM_DEPTH + .addrb(b.a), // Port B address bus, width determined from RAM_DEPTH + .dina(a.d), // Port A RAM input data, width determined from RAM_WIDTH + .dinb(b.d), // Port B RAM input data, width determined from RAM_WIDTH + .clka(a.i_clk), // Port A clock + .clkb(b.i_clk), // Port B clock + .wea(a.we), // Port A write enable + .web(b.we), // Port B write enable + .ena(a.en), // Port A RAM Enable, for additional power savings, disable port when not in use + .enb(b.en), // Port B RAM Enable, for additional power savings, disable port when not in use + .rsta(a.i_rst), // Port A output reset (does not affect memory contents) + .rstb(b.i_rst), // Port B output reset (does not affect memory contents) + .regcea(a.re), // Port A output register enable + .regceb(b.re), // Port B output register enable + .douta(a.q), // Port A RAM output data, width determined from RAM_WIDTH + .doutb(b.q) // Port B RAM output data, width determined from RAM_WIDTH ); endmodule diff --git a/ip_cores/util/src/rtl/dup_check.sv b/ip_cores/util/src/rtl/dup_check.sv new file mode 100644 index 0000000..5defe21 --- /dev/null +++ b/ip_cores/util/src/rtl/dup_check.sv @@ -0,0 +1,148 @@ +/* + This verifies that a input list stream has no duplicates. + + Implemented using a hash table and FIFOs for flow control. + + Input FIFO could be implemented with clock crossing to run at higher frequency. + + Copyright (C) 2019 Benjamin Devlin and Zcash Foundation + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +module dup_check # ( + parameter IN_BITS, + parameter LIST_SIZE +) ( + input i_clk, i_rst, + + if_axi_stream.sink i_axi, // One index per clock cycle - start on .sop and finishes on .eop + if_axi_stream.source o_axi // Will give a single clock cycle output with dat = 0 (no duplicates) or 1 (duplicates) +); + +logic hash_map_out_rdy, hash_map_out_val, hash_map_out_fnd, hash_map_clr, hash_map_full; +logic sol_index_fifo_if_emp; +if_axi_stream #(.DAT_BITS(IN_BITS), .CTL_BITS(1), .MOD_BITS(1)) sol_index_fifo_if_in(i_clk); +if_axi_stream #(.DAT_BITS(IN_BITS), .CTL_BITS(1), .MOD_BITS(1)) sol_index_fifo_if_out(i_clk); + +logic eop_l, fnd_l; + +enum {IDLE = 0, + SEARCH = 1, + CLEAR = 2} dup_check_state; + +always_comb begin + i_axi.rdy = (dup_check_state != CLEAR) && sol_index_fifo_if_in.rdy && ~eop_l; + sol_index_fifo_if_out.rdy = hash_map_out_rdy; + sol_index_fifo_if_in.dat = i_axi.dat; + sol_index_fifo_if_in.eop = 0; + sol_index_fifo_if_in.sop = 0; + sol_index_fifo_if_in.err = 0; + sol_index_fifo_if_in.ctl = 0; + sol_index_fifo_if_in.mod = 0; + sol_index_fifo_if_in.val = i_axi.val; +end + +always_ff @ (posedge i_clk) begin + if (i_rst) begin + dup_check_state <= IDLE; + hash_map_clr <= 0; + eop_l <= 0; + fnd_l <= 0; + o_axi.reset_source(); + end else begin + eop_l <= eop_l || (i_axi.val && i_axi.rdy && i_axi.eop); + fnd_l <= fnd_l || (hash_map_out_val && hash_map_out_fnd); + + o_axi.val <= 0; + o_axi.err <= 0; + o_axi.sop <= 1; + o_axi.eop <= 1; + hash_map_clr <= 0; + + case (dup_check_state) + IDLE: begin + if (~sol_index_fifo_if_emp && hash_map_out_rdy) begin + dup_check_state <= SEARCH; + end + end + SEARCH: begin + + if (sol_index_fifo_if_emp && eop_l && o_axi.rdy) begin + dup_check_state <= CLEAR; + o_axi.val <= 1; + o_axi.dat <= fnd_l; + hash_map_clr <= 1; + end + + end + CLEAR: begin + eop_l <= 0; + fnd_l <= 0; + if (hash_map_out_rdy) + dup_check_state <= IDLE; + end + endcase + + if (hash_map_full) begin + o_axi.err <= 1; + o_axi.val <= 1; + hash_map_clr <= 1; + dup_check_state <= CLEAR; + end + + end +end + + +axi_stream_fifo #( + .SIZE ( LIST_SIZE ), + .DAT_BITS ( IN_BITS ), + .MOD_BITS ( 1 ), + .CTL_BITS ( 1 ), + .USE_BRAM ( 1 ) +) +index_fifo ( + .i_clk ( i_clk ), + .i_rst ( i_rst ), + .i_axi ( sol_index_fifo_if_in ), + .o_axi ( sol_index_fifo_if_out ), + .o_full ( sol_index_fifo_if_full ), + .o_emp ( sol_index_fifo_if_emp ) +); + +// Hash table used to detect duplicate index, fed from FIFO +// Could potentially be run at much higher clock +hash_map #( + .KEY_BITS ( IN_BITS ), + .DAT_BITS ( 1 ), + .HASH_MEM_SIZE ( 2*LIST_SIZE ), + .LL_MEM_SIZE ( LIST_SIZE ) +) +hash_map_i ( + .i_clk ( i_clk ), + .i_rst ( i_rst ), + .i_key ( sol_index_fifo_if_out.dat ), + .i_val ( sol_index_fifo_if_out.val ), + .i_dat ( 1'd1 ), + .i_opcode ( 2'd1 ), + .o_rdy ( hash_map_out_rdy ), + .o_dat (), + .o_val ( hash_map_out_val ), + .o_fnd ( hash_map_out_fnd ), + .i_cfg_clr ( hash_map_clr ), + .o_cfg_full ( hash_map_full ) +); + +endmodule \ No newline at end of file diff --git a/zcash_verif/src/rtl/zcash_verif_equihash.sv b/zcash_verif/src/rtl/zcash_verif_equihash.sv index 1e61ef3..1c38120 100644 --- a/zcash_verif/src/rtl/zcash_verif_equihash.sv +++ b/zcash_verif/src/rtl/zcash_verif_equihash.sv @@ -28,7 +28,8 @@ module zcash_verif_equihash import zcash_verif_pkg::*; #( - parameter DAT_BYTS = 8 + parameter DAT_BYTS = 8, + parameter CHECK_UNIQUE_INDEX = 1 )( input i_clk, i_rst, @@ -61,13 +62,18 @@ if_ram #(.RAM_WIDTH(EQUIHASH_SOL_BRAM_WIDTH), .RAM_DEPTH(EQUIHASH_SOL_BRAM_DEPTH logic [DAT_BITS-1:0] equihash_sol_bram_if_b_l; logic [2*DAT_BITS-1:0] equihash_sol_bram_if_b_l_comb, equihash_sol_bram_if_b_l_comb_flip; -logic [SOL_BITS-1:0] equihash_sol_index, hash_map_in_dat; +logic [SOL_BITS-1:0] equihash_sol_index; logic [1:0] equihash_sol_bram_read; -logic hash_map_in_val, hash_map_out_rdy, hash_map_out_val, hash_map_out_fnd, hash_map_clr, hash_map_full; -logic sol_index_fifo_if_emp; -if_axi_stream #(.DAT_BITS(SOL_BITS), .CTL_BITS(1), .MOD_BITS(1)) sol_index_fifo_if_in(i_clk); -if_axi_stream #(.DAT_BITS(SOL_BITS), .CTL_BITS(1), .MOD_BITS(1)) sol_index_fifo_if_out(i_clk); +logic dup_chk_done, order_chk_done; + +if_axi_stream #(.DAT_BITS(SOL_BITS), .CTL_BITS(1), .MOD_BITS(1)) dup_check_if_in(i_clk); +if_axi_stream #(.DAT_BITS(1), .CTL_BITS(1), .MOD_BITS(1)) dup_check_if_out(i_clk); + +if_axi_stream #(.DAT_BITS(SOL_BITS), .MOD_BITS(1), .CTL_BITS(1)) equihash_order_if(i_clk); +logic equihash_order_val, equihash_order_wrong; + + enum {STATE_WR_IDLE = 0, STATE_WR_DATA = 1, @@ -106,7 +112,7 @@ always_ff @ (posedge i_clk) begin case (ram_wr_state) // This state we are waiting for an input block STATE_WR_IDLE: begin - i_axi.rdy <= hash_map_out_rdy; + i_axi.rdy <= (dup_check_if_in.rdy && equihash_order_if.rdy); if (i_axi.val && i_axi.rdy) begin ram_wr_state <= STATE_WR_DATA; equihash_sol_bram_if_a.a <= 0; @@ -149,6 +155,9 @@ always_ff @ (posedge i_clk) begin equihash_sol_bram_if_b_l <= 0; equihash_gen_in <= 0; equihash_sol_bram_read <= 0; + dup_check_if_in.reset_source(); + equihash_order_if.reset_source(); + ram_rd_state <= STATE_RD_IDLE; end else begin // Defaults @@ -157,6 +166,10 @@ always_ff @ (posedge i_clk) begin blake2b_in_hash.sop <= 1; blake2b_in_hash.eop <= 1; blake2b_in_hash.val <= 0; + + dup_check_if_in.val <= 0; + equihash_order_if.val <= 0; + equihash_sol_bram_read <= equihash_sol_bram_read << 1; if (equihash_sol_bram_read[0]) equihash_sol_bram_if_b_l <= equihash_sol_bram_if_b.q; @@ -191,6 +204,7 @@ always_ff @ (posedge i_clk) begin equihash_gen_in.nonce <= cblockheader.nonce; equihash_gen_in.index <= (equihash_sol_index)/INDICIES_PER_HASH; blake2b_in_hash.ctl <= (equihash_sol_index) % INDICIES_PER_HASH; + // Stay 2 clocks behind the RAM write if ((equihash_sol_bram_if_a.a*DAT_BYTS + DAT_BYTS) >= (equihash_sol_bram_if_b.a + $bits(cblockheader_t)/DAT_BITS) || @@ -204,6 +218,16 @@ always_ff @ (posedge i_clk) begin // Load input into Blake2b block blake2b_in_hash.val <= 1; sol_cnt_in <= sol_cnt_in + 1; + + dup_check_if_in.val <= 1; + dup_check_if_in.dat <= equihash_sol_index; + dup_check_if_in.sop <= (sol_cnt_in == 0); + dup_check_if_in.eop <= (sol_cnt_in == SOL_LIST_LEN - 1); + + equihash_order_if.val <= 1; + equihash_order_if.dat <= equihash_sol_index; + equihash_order_if.sop <= (sol_cnt_in == 0); + equihash_order_if.eop <= (sol_cnt_in == SOL_LIST_LEN - 1); // If our input is about to shift we need to adjust pointer by DAT_BITS sol_pos <= sol_pos + SOL_BITS - (equihash_sol_bram_read[0] ? DAT_BITS : 0); @@ -228,21 +252,34 @@ always_ff @ (posedge i_clk) begin blake2b_out_hash.rdy <= 0; sol_cnt_out <= 0; chk_state <= STATE_CHK_IDLE; - hash_map_clr <= 0; + dup_check_if_out.rdy <= 1; + dup_chk_done <= 0; + order_chk_done <= 0; end else begin // Defaults blake2b_out_hash.rdy <= 1; - hash_map_clr <= 0; - sol_index_fifo_if_in.val <= blake2b_in_hash.val; - sol_index_fifo_if_in.dat <= equihash_sol_index; - - if ( (hash_map_out_val && hash_map_out_fnd) || hash_map_full ) - o_mask.DUPLICATE_FND <= 1; + // Monitor for result of duplicate check + if (dup_check_if_out.val) begin + if (dup_check_if_out.dat[0] || dup_check_if_out.err) begin + o_mask.DUPLICATE_FND <= 1; + end + dup_chk_done <= 1; + end + + // Monitor for result of order check + if (equihash_order_val) begin + if (equihash_order_wrong) begin + o_mask.BAD_IDX_ORDER <= 1; + end + order_chk_done <= 1; + end case(chk_state) STATE_CHK_IDLE: begin sol_cnt_out <= 0; + dup_chk_done <= 0; + order_chk_done <= 0; o_mask_val <= 0; o_mask <= 0; sol_hash_xor <= 0; @@ -275,11 +312,11 @@ always_ff @ (posedge i_clk) begin if (ram_rd_state == STATE_RD_WAIT && ram_wr_state == STATE_WR_WAIT && - sol_index_fifo_if_emp ) begin + dup_chk_done && + order_chk_done ) begin o_mask_val <= 1; chk_state <= STATE_CHK_DONE; - hash_map_clr <= 1; end end STATE_CHK_DONE: begin @@ -309,11 +346,7 @@ always_comb begin // The SOL_BITS is also bit reversed for (int i = 0; i < SOL_BITS; i++) equihash_sol_index[i] = equihash_sol_bram_if_b_l_comb_flip[sol_pos + SOL_BITS-1-i]; - - // Hash map is fed directly from FIFO - hash_map_in_val = sol_index_fifo_if_out.val; - hash_map_in_dat = sol_index_fifo_if_out.dat; - sol_index_fifo_if_out.rdy = hash_map_out_rdy; + end @@ -352,7 +385,7 @@ blake2b_pipe_top_i ( .o_hash ( blake2b_out_hash ) ); -// Memory to store the equihash solution as it comes in. We use dual port, +// Memory to store the compressed equihash solution as it comes in. We use dual port, // one port for writing and one port for reading bram #( .RAM_WIDTH ( EQUIHASH_SOL_BRAM_WIDTH ), @@ -363,44 +396,39 @@ bram #( .b ( equihash_sol_bram_if_b ) ); -axi_stream_fifo #( - .SIZE ( SOL_LIST_LEN ), - .DAT_BITS ( SOL_BITS ), - .MOD_BITS ( 1 ), - .CTL_BITS ( 1 ) -) -sol_index_fifo ( - .i_clk ( i_clk ), - .i_rst ( i_rst ), - .i_axi ( sol_index_fifo_if_in ), - .o_axi ( sol_index_fifo_if_out ), - .o_full (), - .o_emp ( sol_index_fifo_if_emp ) -); - -// Hash table used to detect duplicate index, fed from FIFO -// Could potentially be run at much higher clock -hash_map #( - .KEY_BITS ( SOL_BITS ), - .DAT_BITS ( 1 ), - .HASH_MEM_SIZE ( 2*SOL_LIST_LEN ), - .LL_MEM_SIZE ( SOL_LIST_LEN ) -) -hash_map_i ( +zcash_verif_equihash_order +equihash_order ( .i_clk ( i_clk ), .i_rst ( i_rst ), - .i_key ( hash_map_in_dat ), - .i_val ( hash_map_in_val ), - .i_dat ( 1'd1 ), - .i_opcode ( 2'd1 ), - .o_rdy ( hash_map_out_rdy ), - .o_dat (), - .o_val ( hash_map_out_val ), - .o_fnd ( hash_map_out_fnd ), - .i_cfg_clr ( hash_map_clr ), - .o_cfg_full ( hash_map_full ) + + .i_axi ( equihash_order_if ), + .o_order_wrong ( equihash_order_wrong ), + .o_val ( equihash_order_val ) ); +generate + if (CHECK_UNIQUE_INDEX == 1) begin: GEN_INDEX_CHECK + dup_check #( + .IN_BITS ( SOL_BITS ), + .LIST_SIZE ( SOL_LIST_LEN ) + ) + dup_check( + .i_clk ( i_clk ), + .i_rst ( i_rst ), + + .i_axi ( dup_check_if_in ), + .o_axi ( dup_check_if_out ) + ); + end else begin + always_comb begin + dup_check_if_in.rdy = 1; + dup_check_if_out.val = 1; + dup_check_if_out.eop = 1; + dup_check_if_out.sop = 1; + dup_check_if_out.dat = 0; + end + end +endgenerate // Some checks to make sure our data structures are correct: initial begin assert ($bits(equihash_gen_in_t)/8 == 144) else $fatal(1, "%m %t ERROR: equihash_gen_in_t is not 144 bytes in size", $time); diff --git a/zcash_verif/src/tb/zcash_verif_equihash_tb.sv b/zcash_verif/src/tb/zcash_verif_equihash_tb.sv index ed8894e..21c3570 100644 --- a/zcash_verif/src/tb/zcash_verif_equihash_tb.sv +++ b/zcash_verif/src/tb/zcash_verif_equihash_tb.sv @@ -99,7 +99,7 @@ endtask // Main testbench calls initial begin - #200ns; + #20us; // Let internal memories reset test_block_346();