OpenCores
URL https://opencores.org/ocsvn/iota_pow_vhdl/iota_pow_vhdl/trunk

Subversion Repositories iota_pow_vhdl

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /iota_pow_vhdl
    from Rev 4 to Rev 5
    Reverse comparison

Rev 4 → Rev 5

/trunk/vhdl_altera_de1/curl.vhd
19,7 → 19,7
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.index_table.all;
 
entity curl is
generic
(
30,7 → 30,8
PARALLEL : integer := 5;
INTERN_NONCE_LENGTH : integer := 32;
BITS_MIN_WEIGHT_MAGINUTE_MAX : integer := 26;
DATA_WIDTH : integer := 9
DATA_WIDTH : integer := 9;
NONCE_OFFSET : integer := 162 -- we hope it nevery changes
);
 
port
53,9 → 54,11
 
subtype state_vector_type is std_logic_vector(PARALLEL-1 downto 0);
subtype mid_state_vector_type is std_logic_vector(DATA_WIDTH-1 downto 0);
subtype min_weight_magnitude_type is std_logic_vector(BITS_MIN_WEIGHT_MAGINUTE_MAX-1 downto 0);
 
type curl_state_array is array(integer range <>) of state_vector_type;
type mid_state_array is array(integer range <>) of mid_state_vector_type;
type min_weight_magnitude_array is array(integer range<>) of min_weight_magnitude_type;
 
signal curl_state_low : curl_state_array(STATE_LENGTH-1 downto 0);
signal curl_state_high : curl_state_array(STATE_LENGTH-1 downto 0);
71,10 → 74,19
 
signal binary_nonce : unsigned(INTERN_NONCE_LENGTH-1 downto 0);
signal mask : state_vector_type;
signal min_weight_magnitude : std_logic_vector(BITS_MIN_WEIGHT_MAGINUTE_MAX-1 downto 0);
signal min_weight_magnitude : min_weight_magnitude_type;
 
 
function expand(b : std_logic)
return state_vector_type is
begin
if b = '1' then
return (others => '1');
else
return (others => '0');
end if;
end expand;
begin
overflow <= flag_overflow;
running <= flag_running;
found <= flag_found;
82,13 → 94,16
process (clk_slow)
-- because it looks prettier
variable spi_cmd : std_logic_vector(5 downto 0);
variable wraddr : integer range 0 to 127 := 0;
variable addrptr : unsigned(7 downto 0) := x"00";
begin
if rising_edge(clk_slow) then
if reset='1' then
-- binary_nonce <= (others => '0');
min_weight_magnitude <= (others => '0');
flag_start <= '0';
spi_data_tx <= (others => '0');
-- curl_mid_state_low <= (others => (others => '0'));
-- curl_mid_state_high <= (others => (others => '0'));
addrptr := x"00";
else
flag_start <= '0';
-- new spi data received
95,39 → 110,47
if spi_data_rxen = '1' then
spi_cmd := spi_data_rx(31 downto 26);
case spi_cmd is
when "000000" => -- nop
when "000000" => -- nop (mainly for reading back data)
when "100001" => -- start / stop
if spi_data_rx(0) = '1' then
flag_start <= '1';
end if;
flag_start <= spi_data_rx(0);
when "100101" => -- write to wr address
wraddr := 0;
addrptr := unsigned(spi_data_rx(7 downto 0));
when "100010" => -- write to mid state
curl_mid_state_low(wraddr) <= std_logic_vector(spi_data_rx(DATA_WIDTH-1 downto 0));
curl_mid_state_high(wraddr) <= std_logic_vector(spi_data_rx(DATA_WIDTH+8 downto DATA_WIDTH));
wraddr := wraddr + 1;
if (addrptr <= (STATE_LENGTH/9)-1) then
curl_mid_state_low(to_integer(addrptr)) <= spi_data_rx(DATA_WIDTH-1 downto 0);
curl_mid_state_high(to_integer(addrptr)) <= spi_data_rx(DATA_WIDTH+8 downto DATA_WIDTH);
end if;
spi_data_tx <= spi_data_rx;
addrptr := addrptr + 1;
when "100100" =>
min_weight_magnitude <= spi_data_rx(BITS_MIN_WEIGHT_MAGINUTE_MAX-1 downto 0);
 
when "000001" => -- read flags
spi_data_tx <= "00000000000000000000000000000" & flag_overflow & flag_found & flag_running;
-- this costs an extreme amount of resources
-- interesting only for debugging
spi_data_tx(2 downto 0) <= flag_overflow & flag_found & flag_running;
 
-- for debugging onle ... read back curl_state
-- when "000010" =>
-- spi_addr := spi_data_rx(25 downto 16);
-- spi_data_tx(0+PARALLEL-1 downto 0) <= curl_state_low(to_integer(unsigned(spi_addr)));
-- spi_data_tx(8+PARALLEL-1 downto 8) <= curl_state_high(to_integer(unsigned(spi_addr)));
 
-- for debugging only ... read back mid_state
-- when "000111" =>
-- if (addrptr <= (STATE_LENGTH/9)-1) then
-- spi_data_tx(DATA_WIDTH-1 downto 0) <= curl_mid_state_low(to_integer(addrptr));
-- spi_data_tx(DATA_WIDTH+8 downto DATA_WIDTH) <= curl_mid_state_high(to_integer(addrptr));
-- else
-- spi_data_tx <= (others => '0');
-- end if;
-- addrptr := addrptr + 1; -- dual-used for debugging purposes
when "000011" => -- read nonce
spi_data_tx(31 downto INTERN_NONCE_LENGTH) <= (others => '0');
spi_data_tx(INTERN_NONCE_LENGTH-1 downto 0) <= std_logic_vector(binary_nonce);
when "000100" => -- read mask
spi_data_tx(PARALLEL-1 downto 0) <= mask;
spi_data_tx(31 downto PARALLEL) <= (others => '0');
when "000110" => -- read back parallel-level
spi_data_tx <= std_logic_vector(to_unsigned(PARALLEL, spi_data_tx'length));
when "010101" => -- loop back read test inverted bits
spi_data_tx <= not spi_data_rx;
when "000110" => -- read back parallel-level
spi_data_tx(3 downto 0) <= std_logic_vector(to_unsigned(PARALLEL, 4));
when others =>
spi_data_tx <= (others => '1');
end case;
136,6 → 159,8
end if;
end process;
 
process (clk)
variable state : integer range 0 to 31 := 0;
variable round : integer range 0 to 127 := 0;
142,7 → 167,9
 
variable imask : state_vector_type;
variable i_min_weight_magnitude : std_logic_vector(BITS_MIN_WEIGHT_MAGINUTE_MAX-1 downto 0);
variable i_min_weight_magnitude : min_weight_magnitude_type;
variable tmp_weight_magnitude : min_weight_magnitude_array(0 to PARALLEL-1);
variable i_binary_nonce : unsigned(INTERN_NONCE_LENGTH-1 downto 0);
 
-- temporary registers get optimized away
variable alpha : curl_state_array(STATE_LENGTH-1 downto 0);
149,102 → 176,94
variable beta : curl_state_array(STATE_LENGTH-1 downto 0);
variable gamma : curl_state_array(STATE_LENGTH-1 downto 0);
variable delta : curl_state_array(STATE_LENGTH-1 downto 0);
variable epsilon : curl_state_array(STATE_LENGTH-1 downto 0);
variable tmp_index : integer range 0 to 1023;
variable tmp_mod : integer range 0 to 31;
variable tmp_highest_bit : integer range 0 to 31;
begin
if rising_edge(clk) then
if reset='1' then
state := 0;
round := 0;
flag_found <= '0';
flag_running <= '0';
flag_overflow <= '0';
binary_nonce <= (others => '0');
mask <= (others => '0');
-- curl_state_low <= (others => (others => '0'));
-- curl_state_high <= (others => (others => '0'));
-- tmp_weight_magnitude := (others => (others => '0'));
i_binary_nonce := (others => '0');
imask := (others => '0');
i_min_weight_magnitude := (others => '0');
alpha := (others => (others => '0'));
beta := (others => (others => '0'));
gamma := (others => (others => '0'));
delta := (others => (others => '0'));
tmp_index := 0;
else
case state is
when 0 =>
mask <= imask;
binary_nonce <= i_binary_nonce;
flag_running <= '0';
if flag_start = '1' then
i_binary_nonce := x"00000000";
i_min_weight_magnitude := min_weight_magnitude;
state := 1;
end if;
-- nop until start from spi
when 1 =>
binary_nonce <= (others => '0');
flag_found <= '0';
flag_running <= '1';
flag_overflow <= '0';
state := 8;
when 8 => -- copy mid state and insert nonce
-- pipeline adder for speed
binary_nonce <= binary_nonce + 1;
-- copy and fully expand mid-state to curl-state
for I in 0 to (STATE_LENGTH/DATA_WIDTH)-1 loop
for J in 0 to DATA_WIDTH-1 loop
tmp_index := I*DATA_WIDTH+J;
if tmp_index < 162 or tmp_index > HASH_LENGTH-1 then
if curl_mid_state_low(I)(J) = '1' then
curl_state_low(tmp_index) <= (others => '1');
else
curl_state_low(tmp_index) <= (others => '0');
end if;
if curl_mid_state_high(I)(J) = '1' then
curl_state_high(tmp_index) <= (others => '1');
else
curl_state_high(tmp_index) <= (others => '0');
end if;
if tmp_index < NONCE_OFFSET or tmp_index > NONCE_OFFSET + NONCE_LENGTH - 1 then
curl_state_low(tmp_index) <= expand(curl_mid_state_low(I)(J));
curl_state_high(tmp_index) <= expand(curl_mid_state_high(I)(J));
end if;
end loop;
end loop;
-- -- generate bitmuster in first two trit-arrays of counter depending from PARALLEL setting
-- -- doesn't need additional resources for pow or division because everything is constant
for J in 0 to 1 loop -- TODO make adjustable ... it's okay up to PARALLEL = 9
for I in 0 to PARALLEL-1 loop
tmp_mod := (I/(3**J)) mod 3;
if tmp_mod = 0 then
curl_state_low(162+J)(I) <= '1';
curl_state_high(162+J)(I) <= '1';
elsif tmp_mod = 1 then
curl_state_low(162+J)(I) <= '0';
curl_state_high(162+J)(I) <= '1';
elsif tmp_mod = 2 then
curl_state_low(162+J)(I) <= '1';
curl_state_high(162+J)(I) <= '0';
end if;
-- fill all ... synthesizer is smart enough to optimize away what is not needed
for I in NONCE_OFFSET to NONCE_OFFSET + NONCE_LENGTH - 1 loop
curl_state_low(I) <= expand('1');
curl_state_high(I) <= expand('1');
end loop;
-- calculate log2(x) by determining the place of highest set bit
-- this is calculated on constants, so no logic needed
tmp_highest_bit := 0;
for I in 0 to 31 loop -- 32 is enough ...^^
if to_unsigned(PARALLEL-1, 32)(I) = '1' then
tmp_highest_bit := I;
end if;
end loop;
-- -- generate bitmuster in first trit-arrays of nonce depending on PARALLEL setting
-- this is calculated on constants, so no logic needed
for I in 0 to PARALLEL-1 loop
for J in 0 to tmp_highest_bit loop
curl_state_low(NONCE_OFFSET+J)(I) <= to_unsigned(I, tmp_highest_bit+1)(J);
curl_state_high(NONCE_OFFSET+J)(I) <= not to_unsigned(I, tmp_highest_bit+1)(J);
end loop;
end loop;
 
-- lowest trits for counter from 0 to 4 (for 5bit)
-- curl_state_low(162) <= "01101";
-- curl_state_high(162) <= "11011";
-- curl_state_low(163) <= "00111";
-- curl_state_high(163) <= "11111";
-- insert and convert binary nonce to trinary nonce
-- It's a fake trinary nonce but integer-values are strictly monotonously rising
-- insert and convert binary nonce to ternary nonce
-- It's a fake ternary nonce but integer-values are strictly monotonously rising
-- with integer values of binary nonce.
-- Doesn't bring the exact same result like reference implementation with real
-- trinary adder - but it doesn't matter and it is way faster.
for I in 164 to 164+INTERN_NONCE_LENGTH-1 loop
if binary_nonce(I-164) = '1' then
curl_state_low(I) <= (others => '1');
curl_state_high(I) <= (others => '0');
else
curl_state_low(I) <= (others => '0');
curl_state_high(I) <= (others => '1');
end if;
-- ternary adder - but it doesn't matter and it is way faster.
-- conveniently put nonce counter at the end of nonce
for I in 0 to INTERN_NONCE_LENGTH-1 loop
curl_state_low(NONCE_OFFSET + NONCE_LENGTH - INTERN_NONCE_LENGTH + I) <= expand(i_binary_nonce(I));
curl_state_high(NONCE_OFFSET + NONCE_LENGTH - INTERN_NONCE_LENGTH + I) <= not expand(i_binary_nonce(I));
end loop;
-- fill remaining trits with '11' (=0)
for I in 164+INTERN_NONCE_LENGTH to HASH_LENGTH-1 loop
curl_state_low(I) <= (others => '1');
curl_state_high(I) <= (others => '1');
end loop;
 
-- initialize round-counter
round := NUMBER_OF_ROUNDS;
251,6 → 270,9
state := 10;
when 10 => -- do the curl hash round without any copying needed
if round = 1 then
state := 16;
end if;
for I in 0 to STATE_LENGTH-1 loop
alpha(I) := curl_state_low(index_table(I));
beta(I) := curl_state_high(index_table(I));
261,47 → 283,38
curl_state_low(I) <= not delta(I);
curl_state_high(I) <= (alpha(I) xor gamma(I)) or delta(I);
end loop;
 
round := round - 1;
if round = 0 then
state := 16;
end if;
when 16 => -- find out which solution - if any
imask := (others => '1');
-- doesn't work like the 2nd variant ... why? TODO^^
imask := (others => '0');
-- transform "vertical" trits to "horizontal" bits
-- and compare with min weight magnitude mask
for I in 0 to PARALLEL-1 loop
tmp_weight_magnitude(I) := (others => '0');
for J in 0 to BITS_MIN_WEIGHT_MAGINUTE_MAX-1 loop
if i_min_weight_magnitude(J) = '1' and (curl_state_low(HASH_LENGTH - 1 - J)(I) /= '1' or curl_state_high(HASH_LENGTH - 1 - J)(I) /= '1') then
imask(I) := '0';
end if;
tmp_weight_magnitude(I)(J) := curl_state_low(HASH_LENGTH - 1 - J)(I) and curl_state_high(HASH_LENGTH - 1 - J)(I);
end loop;
tmp_weight_magnitude(I) := tmp_weight_magnitude(I) and i_min_weight_magnitude; -- only consider used bits
if tmp_weight_magnitude(I) = i_min_weight_magnitude then
imask(I) := '1';
end if;
end loop;
-- imask := (others => '1');
-- for I in 0 to BITS_MIN_WEIGHT_MAGINUTE_MAX-1 loop
-- if i_min_weight_magnitude(I) = '1' then
-- imask := imask and not (curl_state_low(HASH_LENGTH - 1 - I) xor curl_state_high(HASH_LENGTH - 1 - I));
-- end if;
-- end loop;
-- mask <= imask;
 
-- no solution found?
if unsigned(imask) = 0 then
-- is overflow?
if binary_nonce = x"ffffffff" then
flag_overflow <= '1';
state := 0;
else
state := 8; -- and try again
end if;
state := 17;
when 17 =>
if unsigned(imask) /= 0 then
state := 30;
elsif i_binary_nonce = x"ffffffff" then
state := 31;
else
state := 30; -- nonce found
i_binary_nonce := i_binary_nonce + 1;
state := 8;
end if;
when 30 =>
mask <= imask;
flag_found <= '1';
state := 0;
when 31 =>
flag_overflow <= '1';
state := 0;
when others =>
state := 0;
end case;
/trunk/vhdl_altera_de1/pll.vhd
146,13 → 146,13
 
altpll_component : altpll
GENERIC MAP (
clk0_divide_by => 1,
clk0_divide_by => 3,
clk0_duty_cycle => 50,
clk0_multiply_by => 4,
clk0_multiply_by => 13,
clk0_phase_shift => "0",
clk1_divide_by => 1,
clk1_divide_by => 6,
clk1_duty_cycle => 50,
clk1_multiply_by => 2,
clk1_multiply_by => 13,
clk1_phase_shift => "0",
compensate_clock => "CLK0",
gate_lock_signal => "NO",
236,12 → 236,12
-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "6"
-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"
-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "3"
-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "6"
-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "200.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "100.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "216.666672"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "108.333336"
-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
266,13 → 266,13
-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1"
-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "13"
-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "13"
-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "200.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "220.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "110.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "0"
281,7 → 281,7
-- Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "ps"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
316,13 → 316,13
-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1"
-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "3"
-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "4"
-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "13"
-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1"
-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "6"
-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "2"
-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "13"
-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
-- Retrieval info: CONSTANT: GATE_LOCK_SIGNAL STRING "NO"
/trunk/vhdl_altera_de1/spi_slave.vhd
3,7 → 3,7
-- Written 2018 by Thomas Pototschnig <microengineer18@gmail.com>
--
-- This source code is currently licensed under
-- Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
-- Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
--
-- http://www.microengineer.eu
--
95,4 → 95,4
end process;
 
end behv;
end behv;
/trunk/vhdl_cyclone10_lp/output_files/curl-cyclone10.sof Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/trunk/vhdl_cyclone10_lp/curl.vhd
15,11 → 15,11
-- GPL and open for any use - commercial included.
 
library ieee;
 
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.index_table.all;
 
entity curl is
generic
(
30,7 → 30,8
PARALLEL : integer := 7;
INTERN_NONCE_LENGTH : integer := 32;
BITS_MIN_WEIGHT_MAGINUTE_MAX : integer := 26;
DATA_WIDTH : integer := 9
DATA_WIDTH : integer := 9;
NONCE_OFFSET : integer := 162 -- we hope it nevery changes
);
 
port
53,9 → 54,11
 
subtype state_vector_type is std_logic_vector(PARALLEL-1 downto 0);
subtype mid_state_vector_type is std_logic_vector(DATA_WIDTH-1 downto 0);
subtype min_weight_magnitude_type is std_logic_vector(BITS_MIN_WEIGHT_MAGINUTE_MAX-1 downto 0);
 
type curl_state_array is array(integer range <>) of state_vector_type;
type mid_state_array is array(integer range <>) of mid_state_vector_type;
type min_weight_magnitude_array is array(integer range<>) of min_weight_magnitude_type;
 
signal curl_state_low : curl_state_array(STATE_LENGTH-1 downto 0);
signal curl_state_high : curl_state_array(STATE_LENGTH-1 downto 0);
71,10 → 74,19
 
signal binary_nonce : unsigned(INTERN_NONCE_LENGTH-1 downto 0);
signal mask : state_vector_type;
signal min_weight_magnitude : std_logic_vector(BITS_MIN_WEIGHT_MAGINUTE_MAX-1 downto 0);
signal min_weight_magnitude : min_weight_magnitude_type;
 
 
function expand(b : std_logic)
return state_vector_type is
begin
if b = '1' then
return (others => '1');
else
return (others => '0');
end if;
end expand;
begin
overflow <= flag_overflow;
running <= flag_running;
found <= flag_found;
82,13 → 94,16
process (clk_slow)
-- because it looks prettier
variable spi_cmd : std_logic_vector(5 downto 0);
variable wraddr : integer range 0 to 127 := 0;
variable addrptr : unsigned(7 downto 0) := x"00";
begin
if rising_edge(clk_slow) then
if reset='1' then
-- binary_nonce <= (others => '0');
min_weight_magnitude <= (others => '0');
flag_start <= '0';
spi_data_tx <= (others => '0');
-- curl_mid_state_low <= (others => (others => '0'));
-- curl_mid_state_high <= (others => (others => '0'));
addrptr := x"00";
else
flag_start <= '0';
-- new spi data received
95,39 → 110,47
if spi_data_rxen = '1' then
spi_cmd := spi_data_rx(31 downto 26);
case spi_cmd is
when "000000" => -- nop
when "000000" => -- nop (mainly for reading back data)
when "100001" => -- start / stop
if spi_data_rx(0) = '1' then
flag_start <= '1';
end if;
flag_start <= spi_data_rx(0);
when "100101" => -- write to wr address
wraddr := 0;
addrptr := unsigned(spi_data_rx(7 downto 0));
when "100010" => -- write to mid state
curl_mid_state_low(wraddr) <= std_logic_vector(spi_data_rx(DATA_WIDTH-1 downto 0));
curl_mid_state_high(wraddr) <= std_logic_vector(spi_data_rx(DATA_WIDTH+8 downto DATA_WIDTH));
wraddr := wraddr + 1;
if (addrptr <= (STATE_LENGTH/9)-1) then
curl_mid_state_low(to_integer(addrptr)) <= spi_data_rx(DATA_WIDTH-1 downto 0);
curl_mid_state_high(to_integer(addrptr)) <= spi_data_rx(DATA_WIDTH+8 downto DATA_WIDTH);
end if;
spi_data_tx <= spi_data_rx;
addrptr := addrptr + 1;
when "100100" =>
min_weight_magnitude <= spi_data_rx(BITS_MIN_WEIGHT_MAGINUTE_MAX-1 downto 0);
 
when "000001" => -- read flags
spi_data_tx <= "00000000000000000000000000000" & flag_overflow & flag_found & flag_running;
-- this costs an extreme amount of resources
-- interesting only for debugging
spi_data_tx(2 downto 0) <= flag_overflow & flag_found & flag_running;
 
-- for debugging onle ... read back curl_state
-- when "000010" =>
-- spi_addr := spi_data_rx(25 downto 16);
-- spi_data_tx(0+PARALLEL-1 downto 0) <= curl_state_low(to_integer(unsigned(spi_addr)));
-- spi_data_tx(8+PARALLEL-1 downto 8) <= curl_state_high(to_integer(unsigned(spi_addr)));
 
-- for debugging only ... read back mid_state
-- when "000111" =>
-- if (addrptr <= (STATE_LENGTH/9)-1) then
-- spi_data_tx(DATA_WIDTH-1 downto 0) <= curl_mid_state_low(to_integer(addrptr));
-- spi_data_tx(DATA_WIDTH+8 downto DATA_WIDTH) <= curl_mid_state_high(to_integer(addrptr));
-- else
-- spi_data_tx <= (others => '0');
-- end if;
-- addrptr := addrptr + 1; -- dual-used for debugging purposes
when "000011" => -- read nonce
spi_data_tx(31 downto INTERN_NONCE_LENGTH) <= (others => '0');
spi_data_tx(INTERN_NONCE_LENGTH-1 downto 0) <= std_logic_vector(binary_nonce);
when "000100" => -- read mask
spi_data_tx(PARALLEL-1 downto 0) <= mask;
spi_data_tx(31 downto PARALLEL) <= (others => '0');
when "010101" => -- loop back read test inverted bits
spi_data_tx <= not spi_data_rx;
when "000110" => -- read back parallel-level
spi_data_tx <= std_logic_vector(to_unsigned(PARALLEL, spi_data_tx'length));
spi_data_tx(3 downto 0) <= std_logic_vector(to_unsigned(PARALLEL, 4));
when others =>
spi_data_tx <= (others => '1');
end case;
136,6 → 159,8
end if;
end process;
 
process (clk)
variable state : integer range 0 to 31 := 0;
variable round : integer range 0 to 127 := 0;
142,7 → 167,9
 
variable imask : state_vector_type;
variable i_min_weight_magnitude : std_logic_vector(BITS_MIN_WEIGHT_MAGINUTE_MAX-1 downto 0);
variable i_min_weight_magnitude : min_weight_magnitude_type;
variable tmp_weight_magnitude : min_weight_magnitude_array(0 to PARALLEL-1);
variable i_binary_nonce : unsigned(INTERN_NONCE_LENGTH-1 downto 0);
 
-- temporary registers get optimized away
variable alpha : curl_state_array(STATE_LENGTH-1 downto 0);
149,102 → 176,94
variable beta : curl_state_array(STATE_LENGTH-1 downto 0);
variable gamma : curl_state_array(STATE_LENGTH-1 downto 0);
variable delta : curl_state_array(STATE_LENGTH-1 downto 0);
variable epsilon : curl_state_array(STATE_LENGTH-1 downto 0);
variable tmp_index : integer range 0 to 1023;
variable tmp_mod : integer range 0 to 31;
variable tmp_highest_bit : integer range 0 to 31;
begin
if rising_edge(clk) then
if reset='1' then
state := 0;
round := 0;
flag_found <= '0';
flag_running <= '0';
flag_overflow <= '0';
binary_nonce <= (others => '0');
mask <= (others => '0');
-- curl_state_low <= (others => (others => '0'));
-- curl_state_high <= (others => (others => '0'));
-- tmp_weight_magnitude := (others => (others => '0'));
i_binary_nonce := (others => '0');
imask := (others => '0');
i_min_weight_magnitude := (others => '0');
alpha := (others => (others => '0'));
beta := (others => (others => '0'));
gamma := (others => (others => '0'));
delta := (others => (others => '0'));
tmp_index := 0;
else
case state is
when 0 =>
mask <= imask;
binary_nonce <= i_binary_nonce;
flag_running <= '0';
if flag_start = '1' then
i_binary_nonce := x"00000000";
i_min_weight_magnitude := min_weight_magnitude;
state := 1;
end if;
-- nop until start from spi
when 1 =>
binary_nonce <= (others => '0');
flag_found <= '0';
flag_running <= '1';
flag_overflow <= '0';
state := 8;
when 8 => -- copy mid state and insert nonce
-- pipeline adder for speed
binary_nonce <= binary_nonce + 1;
-- copy and fully expand mid-state to curl-state
for I in 0 to (STATE_LENGTH/DATA_WIDTH)-1 loop
for J in 0 to DATA_WIDTH-1 loop
tmp_index := I*DATA_WIDTH+J;
if tmp_index < 162 or tmp_index > HASH_LENGTH-1 then
if curl_mid_state_low(I)(J) = '1' then
curl_state_low(tmp_index) <= (others => '1');
else
curl_state_low(tmp_index) <= (others => '0');
end if;
if curl_mid_state_high(I)(J) = '1' then
curl_state_high(tmp_index) <= (others => '1');
else
curl_state_high(tmp_index) <= (others => '0');
end if;
if tmp_index < NONCE_OFFSET or tmp_index > NONCE_OFFSET + NONCE_LENGTH - 1 then
curl_state_low(tmp_index) <= expand(curl_mid_state_low(I)(J));
curl_state_high(tmp_index) <= expand(curl_mid_state_high(I)(J));
end if;
end loop;
end loop;
-- -- generate bitmuster in first two trit-arrays of counter depending from PARALLEL setting
-- -- doesn't need additional resources for pow or division because everything is constant
for J in 0 to 1 loop -- TODO make adjustable ... it's okay up to PARALLEL = 9
for I in 0 to PARALLEL-1 loop
tmp_mod := (I/(3**J)) mod 3;
if tmp_mod = 0 then
curl_state_low(162+J)(I) <= '1';
curl_state_high(162+J)(I) <= '1';
elsif tmp_mod = 1 then
curl_state_low(162+J)(I) <= '0';
curl_state_high(162+J)(I) <= '1';
elsif tmp_mod = 2 then
curl_state_low(162+J)(I) <= '1';
curl_state_high(162+J)(I) <= '0';
end if;
-- fill all ... synthesizer is smart enough to optimize away what is not needed
for I in NONCE_OFFSET to NONCE_OFFSET + NONCE_LENGTH - 1 loop
curl_state_low(I) <= expand('1');
curl_state_high(I) <= expand('1');
end loop;
-- calculate log2(x) by determining the place of highest set bit
-- this is calculated on constants, so no logic needed
tmp_highest_bit := 0;
for I in 0 to 31 loop -- 32 is enough ...^^
if to_unsigned(PARALLEL-1, 32)(I) = '1' then
tmp_highest_bit := I;
end if;
end loop;
-- -- generate bitmuster in first trit-arrays of nonce depending on PARALLEL setting
-- this is calculated on constants, so no logic needed
for I in 0 to PARALLEL-1 loop
for J in 0 to tmp_highest_bit loop
curl_state_low(NONCE_OFFSET+J)(I) <= to_unsigned(I, tmp_highest_bit+1)(J);
curl_state_high(NONCE_OFFSET+J)(I) <= not to_unsigned(I, tmp_highest_bit+1)(J);
end loop;
end loop;
 
-- lowest trits for counter from 0 to 4 (for 5bit)
-- curl_state_low(162) <= "01101";
-- curl_state_high(162) <= "11011";
-- curl_state_low(163) <= "00111";
-- curl_state_high(163) <= "11111";
-- insert and convert binary nonce to trinary nonce
-- It's a fake trinary nonce but integer-values are strictly monotonously rising
-- insert and convert binary nonce to ternary nonce
-- It's a fake ternary nonce but integer-values are strictly monotonously rising
-- with integer values of binary nonce.
-- Doesn't bring the exact same result like reference implementation with real
-- trinary adder - but it doesn't matter and it is way faster.
for I in 164 to 164+INTERN_NONCE_LENGTH-1 loop
if binary_nonce(I-164) = '1' then
curl_state_low(I) <= (others => '1');
curl_state_high(I) <= (others => '0');
else
curl_state_low(I) <= (others => '0');
curl_state_high(I) <= (others => '1');
end if;
-- ternary adder - but it doesn't matter and it is way faster.
-- conveniently put nonce counter at the end of nonce
for I in 0 to INTERN_NONCE_LENGTH-1 loop
curl_state_low(NONCE_OFFSET + NONCE_LENGTH - INTERN_NONCE_LENGTH + I) <= expand(i_binary_nonce(I));
curl_state_high(NONCE_OFFSET + NONCE_LENGTH - INTERN_NONCE_LENGTH + I) <= not expand(i_binary_nonce(I));
end loop;
-- fill remaining trits with '11' (=0)
for I in 164+INTERN_NONCE_LENGTH to HASH_LENGTH-1 loop
curl_state_low(I) <= (others => '1');
curl_state_high(I) <= (others => '1');
end loop;
 
-- initialize round-counter
round := NUMBER_OF_ROUNDS;
251,6 → 270,9
state := 10;
when 10 => -- do the curl hash round without any copying needed
if round = 1 then
state := 16;
end if;
for I in 0 to STATE_LENGTH-1 loop
alpha(I) := curl_state_low(index_table(I));
beta(I) := curl_state_high(index_table(I));
261,47 → 283,38
curl_state_low(I) <= not delta(I);
curl_state_high(I) <= (alpha(I) xor gamma(I)) or delta(I);
end loop;
 
round := round - 1;
if round = 0 then
state := 16;
end if;
when 16 => -- find out which solution - if any
imask := (others => '1');
-- doesn't work like the 2nd variant ... why? TODO^^
imask := (others => '0');
-- transform "vertical" trits to "horizontal" bits
-- and compare with min weight magnitude mask
for I in 0 to PARALLEL-1 loop
tmp_weight_magnitude(I) := (others => '0');
for J in 0 to BITS_MIN_WEIGHT_MAGINUTE_MAX-1 loop
if i_min_weight_magnitude(J) = '1' and (curl_state_low(HASH_LENGTH - 1 - J)(I) /= '1' or curl_state_high(HASH_LENGTH - 1 - J)(I) /= '1') then
imask(I) := '0';
end if;
tmp_weight_magnitude(I)(J) := curl_state_low(HASH_LENGTH - 1 - J)(I) and curl_state_high(HASH_LENGTH - 1 - J)(I);
end loop;
tmp_weight_magnitude(I) := tmp_weight_magnitude(I) and i_min_weight_magnitude; -- only consider used bits
if tmp_weight_magnitude(I) = i_min_weight_magnitude then
imask(I) := '1';
end if;
end loop;
-- imask := (others => '1');
-- for I in 0 to BITS_MIN_WEIGHT_MAGINUTE_MAX-1 loop
-- if i_min_weight_magnitude(I) = '1' then
-- imask := imask and not (curl_state_low(HASH_LENGTH - 1 - I) xor curl_state_high(HASH_LENGTH - 1 - I));
-- end if;
-- end loop;
-- mask <= imask;
 
-- no solution found?
if unsigned(imask) = 0 then
-- is overflow?
if binary_nonce = x"ffffffff" then
flag_overflow <= '1';
state := 0;
else
state := 8; -- and try again
end if;
state := 17;
when 17 =>
if unsigned(imask) /= 0 then
state := 30;
elsif i_binary_nonce = x"ffffffff" then
state := 31;
else
state := 30; -- nonce found
i_binary_nonce := i_binary_nonce + 1;
state := 8;
end if;
when 30 =>
mask <= imask;
flag_found <= '1';
state := 0;
when 31 =>
flag_overflow <= '1';
state := 0;
when others =>
state := 0;
end case;
/trunk/vhdl_cyclone10_lp/pll.vhd
148,11 → 148,11
altpll_component : altpll
GENERIC MAP (
bandwidth_type => "AUTO",
clk0_divide_by => 5,
clk0_divide_by => 2,
clk0_duty_cycle => 50,
clk0_multiply_by => 14,
clk0_multiply_by => 7,
clk0_phase_shift => "0",
clk1_divide_by => 5,
clk1_divide_by => 4,
clk1_duty_cycle => 50,
clk1_multiply_by => 7,
clk1_phase_shift => "0",
237,12 → 237,12
-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "Any"
-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"
-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "2"
-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "4"
-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "140.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "70.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "175.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "87.500000"
-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
267,13 → 267,13
-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1"
-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "7"
-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "7"
-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "140.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "175.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "70.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
317,11 → 317,11
-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "5"
-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "2"
-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "14"
-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "7"
-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "5"
-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "4"
-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "7"
-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
/trunk/vhdl_cyclone10_lp/spi_slave.vhd
1,3 → 1,19
-- IOTA Pearl Diver VHDL Port
--
-- Written 2018 by Thomas Pototschnig <microengineer18@gmail.com>
--
-- This source code is currently licensed under
-- Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
--
-- http://www.microengineer.eu
--
-- If you like my project please consider a donation to
--
-- LLEYMHRKXWSPMGCMZFPKKTHSEMYJTNAZXSAYZGQUEXLXEEWPXUNWBFDWESOJVLHQHXOPQEYXGIRBYTLRWHMJAOSHUY
--
-- As soon as donations reach 1000MIOTA, everything will become
-- GPL and open for any use - commercial included.
 
library ieee;
 
use ieee.std_logic_1164.all;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.