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/trunk/vhdl_altera_de1
- from Rev 4 to Rev 5
- ↔ Reverse comparison
Rev 4 → Rev 5
/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; |
/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" |
/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; |