Darky777 0 3 июля, 2019 Опубликовано 3 июля, 2019 (изменено) · Жалоба Приветствую! Многие кто пишет на SystemVerilog/Verilog знаком с оператором для динамического выбора нужных кусков вектора/переменной/массива_регистров. +: -: Больше часа ломал голову, как применить его в моем случае, может под вечер устал и не соображаю. Вот то, что мне нужен сделать (если бы стандарт верилога поддерживал такую запись для варьируемого индекса) data_o <= {buffer[4+shift_size-1:4],tmp[4:shift_size-1]}; Подскажите, пожалуйста, как описать такую конструкцию? ведь в ней варьируемая ширина вектора, а не фиксированная часть. Поддерживает ли верилог подобные штуки? Вот весь код. Сразу отвечаю, что пока не симулил, т.к. смысла нет (синтаксическая ошибка range must be bounded by constant expressions), и обычно планирую это делать следующим этапом, пока что я уперся в это. Если есть желающие, то прошу оставить обратную связь касательно кода. Буду рад любой аргументированной критике. Под Vivado 2018.2 module frame_aligner ( input clk_i , // Clock input arst_n , // Asynchronous reset active low input sync_i , input [3:0] data_i , output logic [5:0] data_o , output logic valid_o , // duty cycle = 2/3 output logic synced_o ); localparam SYNC_PATT = 12'b111111_000000; localparam SYNC_PATT_MR = ~SYNC_PATT; /*------------------------------------------------------------------------------ -- Functions ------------------------------------------------------------------------------*/ function automatic int unsigned clogb2_pure_f( input [31:0] value ); int unsigned i ; int unsigned temp ; begin temp = 32; for (i=31; i>0; i=i-1) begin if (2**i >= value) begin temp = i; end end return temp ; end endfunction function automatic logic [11:0] dynamic_shift_f ( input [11:0] data_i, input [clogb2_pure_f(12) - 1:0] ss); dynamic_shift_f = data_i; for (int i = 0; i < ss; i++) begin dynamic_shift_f = {dynamic_shift_f[0],dynamic_shift_f[11:1]}; end return dynamic_shift_f; endfunction /*------------------------------------------------------------------------------ -- Signals declaration ------------------------------------------------------------------------------*/ logic sync_ff,sync_fr,sync_cdc; typedef enum logic [1:0] { INIT, FIND_PATTERN, SYNC_MODE_SHIFT,SYNC_MODE_ZERO } fsm_t; fsm_t state, state_next; logic [ 1:0] cnt ; logic [11:0] buffer ; logic strb ; logic [11:0] shifted_data; logic [ 4:0] tmp ; logic match; logic [2:0] shift_size,shift_size_event; /*------------------------------------------------------------------------------ -- Clock Domain crossing ------------------------------------------------------------------------------*/ synchronize_ff #(.FF_CNT(3)) i_synchronize_ff (.clk_i(clk_i), .rstn_i(arst_n), .data_i(sync_i), .data_o(sync_cdc)); always_ff @(posedge clk_i or negedge arst_n) begin : proc_sync_ff if(~arst_n) begin sync_ff <= 0; end else begin sync_ff <= sync_cdc; end end assign sync_fr = !sync_ff && sync_cdc; /*------------------------------------------------------------------------------ -- Functional ------------------------------------------------------------------------------*/ always_ff @(posedge clk_i or negedge arst_n) begin : proc_cnt if(~arst_n) begin cnt <= 0; end else begin cnt <= cnt < 2 ? cnt + 1'b1 : '0; end end assign strb = cnt == 2; always_ff @(posedge clk_i or negedge arst_n) begin : proc_buffer if(~arst_n) begin buffer <= 0; end else begin buffer <= {data_i,buffer[7:4]}; end end always_ff @(posedge clk_i or negedge arst_n) begin : proc_shift_size if(~arst_n) begin shift_size <= 0; end else if ( strb ) begin if( state == FIND_PATTERN ) begin if( !match ) begin shift_size <= shift_size < 5 ? shift_size + 1'b1 : '0 ; end else begin shift_size <= shift_size < 5 ? shift_size + 1'b1 : '0 ; end end end end assign shift_size_event = ( shift_size != 0 ) ? ( 5 ) : ( shift_size - 1 ); always_ff @(posedge clk_i or negedge arst_n) begin : proc_shifted_data if(~arst_n) begin shifted_data <= 0; end else if (strb) begin shifted_data <= dynamic_shift_f(buffer,shift_size); end end assign match = ( shifted_data == SYNC_PATT ) || ( shifted_data == SYNC_PATT ); /*------------------------------------------------------------------------------ -- FSM ------------------------------------------------------------------------------*/ always_ff @(posedge clk_i or negedge arst_n) begin : proc_state if(~arst_n) begin state <= INIT; end else begin state <= state_next; end end always_comb begin : proc_state_next state_next = state; case (state) INIT : state_next = ( sync_fr ) ? ( FIND_PATTERN ): ( state ); FIND_PATTERN : state_next = ( match ) ? ((shift_size_event != 0 ) ? (SYNC_MODE_SHIFT) : (SYNC_MODE_ZERO)): ( state ) ; SYNC_MODE_SHIFT : state_next = state; SYNC_MODE_ZERO : state_next = state; default : state_next = INIT ; endcase end /*------------------------------------------------------------------------------ -- data to output ------------------------------------------------------------------------------*/ always_ff @(posedge clk_i or negedge arst_n) begin : proc_data_o if(~arst_n) begin data_o <= '0; valid_o <= 1'b0; tmp <= '0; end else begin case (state) SYNC_MODE_SHIFT : begin case (cnt) 1 : begin data_o <= {buffer[4+shift_size-1:4],tmp[4:shift_size-1]}; // ВОТ ТУТ! valid_o <= 1'b1; end 2 : begin data_o <= buffer[shift_size +:6]; tmp <= buffer[11:7]; valid_o <= 1'b1; end default : begin data_o <= data_o; valid_o <= 1'b0; end endcase end SYNC_MODE_ZERO : begin case (cnt) 1 : begin data_o <= buffer[7:2]; end 2 : begin data_o <= buffer[5:0]; end default : begin data_o <= data_o; valid_o <= 1'b0; end endcase end default : data_o <= data_o; endcase end end always_ff @(posedge clk_i or negedge arst_n) begin : proc_synced_o if(~arst_n) begin synced_o <= 1'b0; end else if ( match ) begin synced_o <= 1'b1; end end endmodule Изменено 3 июля, 2019 пользователем Darky777 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 3 июля, 2019 Опубликовано 3 июля, 2019 · Жалоба Приветствую! Работу с частью вектора с динамической шириной в verilog можно делать используя битовые маски, битовые операции, и сдвиги например в вашем случае (если я правильно понял логику) все просто data_o <= ({buffer[11:4],tmp[4:0]}<<1) >> shift_size; Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darky777 0 3 июля, 2019 Опубликовано 3 июля, 2019 (изменено) · Жалоба 1 hour ago, RobFPGA said: Приветствую! Работу с частью вектора с динамической шириной в verilog можно делать используя битовые маски, битовые операции, и сдвиги например в вашем случае (если я правильно понял логику) все просто data_o <= ({buffer[11:4],tmp[4:0]}<<1) >> shift_size; Удачи! Rob. Спасибо за ответ! Я попробую.. Мне когда-то сказали, что оператор логического сдвига не всегда корректно интерпретируется синтезатором, поэтому если необходимо польоваться сдвигом, я использую конструкцию data <= {data[$bits(data) - 2:0],1'b0}; что думаете об этом? Изменено 3 июля, 2019 пользователем Darky777 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 3 июля, 2019 Опубликовано 3 июля, 2019 · Жалоба Приветствую! 7 hours ago, Darky777 said: ... Я попробую.. Мне когда-то сказали, что оператор логического сдвига не всегда корректно интерпретируется синтезатором, поэтому если необходимо польоваться сдвигом, я использую конструкцию data <= {data[$bits(data) - 2:0],1'b0}; что думаете об этом? Ох, эти рассказчики - наговорят всякого а народ верит Если не уверенны во что это синтезируется вам никто не мешает слепить тестовый модулек Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 4 июля, 2019 Опубликовано 4 июля, 2019 · Жалоба 11 hours ago, Darky777 said: Я попробую.. Мне когда-то сказали, что оператор логического сдвига не всегда корректно интерпретируется синтезатором, поэтому если необходимо польоваться сдвигом, я использую конструкцию Вполне справедливо, если говорить про ISE+vhdl. Вивада стала более продвинутой и посему такие приколы происходят реже. Кстати имеется вопрос по теме. У меня конструкция типа parameter C_S_AXI_DATA_WIDTH = 32; parameter C_S_AXI_ADDR_WIDTH = 5; localparam p_num = 32; localparam p_word_bits = 32; localparam p_bits_per = 16; logic [2**C_S_AXI_ADDR_WIDTH - 1 : 0][C_S_AXI_DATA_WIDTH - 1 : 0] internal_reg; logic [p_num - 1 : 0][p_bits_per - 1 : 0] r_csr; always foreach (r_csr[i]) r_csr[i] <= {internal_reg}[(p_word_bits + (i * p_bits_per)) +: p_bits_per]; Выдаёт ошибку: [Synth 8-524] part-select [543:528] out of range of prefix ''Undefined'' но если сделать те же манипуляции через нэт, тогда всё отлично работает. Хотелось узнать в чём специфика? Индексы вроде как обозначаются через простые интеджеры. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 4 июля, 2019 Опубликовано 4 июля, 2019 · Жалоба Приветствую! 7 minutes ago, Nick_K said: ... parameter C_S_AXI_ADDR_WIDTH = 5; logic [2**C_S_AXI_ADDR_WIDTH - 1 : 0][C_S_AXI_DATA_WIDTH - 1 : 0] internal_reg; logic [p_num - 1 : 0][p_bits_per - 1 : 0] r_csr; always foreach (r_csr[i]) r_csr[i] <= {internal_reg}[(p_word_bits + (i * p_bits_per)) +: p_bits_per]; Выдаёт ошибку: [Synth 8-524] part-select [543:528] out of range of prefix ''Undefined'' но если сделать те же манипуляции через нэт, тогда всё отлично работает. Хотелось узнать в чём специфика? Индексы вроде как обозначаются через простые интеджеры. Странно - а в чем синтезировали? Может при синтезе параметр C_S_AXI_ADDR_WIDTH был равен 4 ? Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 4 июля, 2019 Опубликовано 4 июля, 2019 · Жалоба 25 minutes ago, RobFPGA said: Странно - а в чем синтезировали? Может при синтезе параметр C_S_AXI_ADDR_WIDTH был равен 4 ? Стандартными средствами: Vivado 2019.1, Linux x64. Особо не разгонишься тут) Параметр не менялся. Он идёт через порт и везде копипаст одинаковый. Говорю же, если сделать временную переменную wire logic [(2**C_S_AXI_ADDR_WIDTH)*C_S_AXI_DATA_WIDTH - 1 : 0] r_vector_internal = {internal_reg}; и работать с ней, тогда всё отлично синтезится. Что собственно и удивило. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darky777 0 5 июля, 2019 Опубликовано 5 июля, 2019 · Жалоба Забыл отписаться. Еще раз благодарю за помощь! On 7/3/2019 at 8:52 PM, RobFPGA said: Работу с частью вектора с динамической шириной в verilog можно делать используя битовые маски, битовые операции, и сдвиги Решил этот момент следующим образом. //... assign tmp_s = {buffer[8:4],tmp} >> (shift_size - 1); //... data_o <= tmp_s[5:0]; //... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться