dimka76 42 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба Здравствуйте. ПЛИСами занимаюсь редко и мало. Использую их в качестве дополнительной периферии для микроконтроллеров. Проекты низкоскоростные. Но вот сейчас похоже скорости стало не хватать. Про констрейны читал. Но понимание и практика их применения нулевая. Раньше хватало скоростей без констрейнов. Итак. FPGA Lattice XP2. Среда Diamond. Synthesize Tool - Symplify Pro. Внутренняя частота, вырабатываемая внутренней PLL, от которой все тактируется, 125 МГц. Сейчас временной анализ показывает, что актуальная получается 125,4 МГц. И я переживаю, что запасик уж очень маленький. Наибольшая задержка идет в модуле RM1. Причем этот модуль от внешних сигналов не зависит, а только все от внутренних, привязанных к внутренней частоте. Вот сам код модуля module reg_mux( input wire clk, input wire i_rst, input wire [11:0] sel, input wire strob, input wire [31:0] data_in_1, input wire [31:0] data_in_2, input wire [31:0] data_in_3, input wire [31:0] z_in_1, input wire [31:0] z_in_2, input wire [31:0] z_in_3, output reg [15:0] data_out ); reg [15:0] register; always @(posedge clk or posedge i_rst) begin if(i_rst) begin data_out[15:0] <= 16'd0; register[15:0] <= 16'd0; end else if(strob) case(sel) 12'b000000000001 : begin register[15:0] <= data_in_1[31:16]; data_out[15:0] <= data_in_1[15:0]; end 12'b000000000100 : begin register[15:0] <= data_in_2[31:16]; data_out[15:0] <= data_in_2[15:0]; end 12'b000000010000 : begin register[15:0] <= data_in_3[31:16]; data_out[15:0] <= data_in_3[15:0]; end 12'b000001000000 : begin register[15:0] <= z_in_1[31:16]; data_out[15:0] <= z_in_1[15:0]; end 12'b000100000000 : begin register[15:0] <= z_in_2[31:16]; data_out[15:0] <= z_in_2[15:0]; end 12'b010000000000 : begin register[15:0] <= z_in_3[31:16]; data_out[15:0] <= z_in_3[15:0]; end 12'b000000000010, 12'b000000001000, 12'b000000100000, 12'b000010000000, 12'b001000000000, 12'b100000000000 : data_out[15:0] <= register[15:0]; default : begin data_out[15:0] <= 16'd0; register[15:0] <= 16'd0; end endcase end endmodule Что можно сделать, чтобы поднять максимальную частоту и тем самым увеличить запас по быстродействию ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба 9 minutes ago, dimka76 said: Что можно сделать, чтобы поднять максимальную частоту и тем самым увеличить запас по быстродействию ? избавиться от 12 ти битных "адресов", а вот способы избавления есть разные) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба 12 минут назад, dimka76 сказал: Что можно сделать, чтобы поднять максимальную частоту и тем самым увеличить запас по быстродействию ? Вместо мультиплексора взять распределенную память, если в лэтисе она есть. С минимальной латентностью... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба Приветствую! 4 minutes ago, dimka76 said: И я переживаю, что запасик уж очень маленький. Наибольшая задержка идет в модуле RM1. Причем этот модуль от внешних сигналов не зависит, а только все от внутренних, привязанных к внутренней частоте. Не переживайте - раз запасец есть то будет работать в определенных условиях окружения (температура и напряжений). Ну а по коду в вашем случае можно посоветовать предварительно декодировать селектор sel на такт раньше с регистром на выходе. Это уменьшит крит. путь для mux. Естественно если это допустимо по логике дизайна. 1 minute ago, iosifk said: Вместо мультиплексора взять распределенную память, если в лэтисе она есть. С минимальной латентностью... Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 42 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба 21 minutes ago, des00 said: избавиться от 12 ти битных "адресов", а вот способы избавления есть разные) module reg_mux( input wire clk, input wire i_rst, input wire [11:0] sel, input wire strob, input wire [31:0] data_in_1, input wire [31:0] data_in_2, input wire [31:0] data_in_3, input wire [31:0] z_in_1, input wire [31:0] z_in_2, input wire [31:0] z_in_3, output reg [15:0] data_out ); reg [15:0] register; always @(posedge clk or posedge i_rst) begin if(i_rst) begin data_out[15:0] <= 16'd0; register[15:0] <= 16'd0; end else if(strob) begin if(sel[0]) begin register[15:0] <= data_in_1[31:16]; data_out[15:0] <= data_in_1[15:0]; end if(sel[2]) begin register[15:0] <= data_in_2[31:16]; data_out[15:0] <= data_in_2[15:0]; end if(sel[4]) begin register[15:0] <= data_in_3[31:16]; data_out[15:0] <= data_in_3[15:0]; end if(sel[6]) begin register[15:0] <= z_in_1[31:16]; data_out[15:0] <= z_in_1[15:0]; end if(sel[8]) begin register[15:0] <= z_in_2[31:16]; data_out[15:0] <= z_in_2[15:0]; end if(sel[10]) begin register[15:0] <= z_in_3[31:16]; data_out[15:0] <= z_in_3[15:0]; end if(sel[1] || sel[3] || sel[5] || sel[7] || sel[9] || sel[11]) data_out[15:0] <= register[15:0]; end end endmodule Попробовал так. Частота выросла до 131 МГц. 17 minutes ago, RobFPGA said: Ну а по коду в вашем случае можно посоветовать предварительно декодировать селектор sel на такт раньше с регистром на выходе. Это уменьшит крит. путь для mux. Естественно если это допустимо по логике дизайна. Это интересно, но не понял сути идеи. Что именно должно быть на выходе предлагаемого вами декодера ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба 16 minutes ago, dimka76 said: always @(posedge clk or posedge i_rst) begin if(i_rst) begin data_out[15:0] <= 16'd0; register[15:0] <= 16'd0; end else if(strob) begin if(sel[0]) begin register[15:0] <= data_in_1[31:16]; data_out[15:0] <= data_in_1[15:0]; end if(sel[2]) begin register[15:0] <= data_in_2[31:16]; data_out[15:0] <= data_in_2[15:0]; end if(sel[4]) begin register[15:0] <= data_in_3[31:16]; data_out[15:0] <= data_in_3[15:0]; end if(sel[6]) begin register[15:0] <= z_in_1[31:16]; data_out[15:0] <= z_in_1[15:0]; end if(sel[8]) begin register[15:0] <= z_in_2[31:16]; data_out[15:0] <= z_in_2[15:0]; end if(sel[10]) begin register[15:0] <= z_in_3[31:16]; data_out[15:0] <= z_in_3[15:0]; end if(sel[1] || sel[3] || sel[5] || sel[7] || sel[9] || sel[11]) data_out[15:0] <= register[15:0]; end end В этом месте было бы хорошо разделить на 2 процесса (читай вставить дополнительные промежуточные регистры): по чётным унарным сигналам захлопывать данные в промежуточный pipeline FF (ну или просто в промежуточный регистр), а уже по нечётным засовывать в выходной сдвиговый регистр. Что-то типа такого: always @(posedge clk or posedge i_rst) begin ... else if(strob) begin if(sel[0]) pipe_ff <= data_in_1; if(sel[2]) pipe_ff <= data_in_2; if(sel[4]) pipe_ff <= data_in_3; if(sel[6]) pipe_ff <= z_in_1; if(sel[8]) pipe_ff <= z_in_2; if(sel[10]) pipe_ff <= z_in_3; end end always @(posedge clk or posedge i_rst) begin ... if(strob) begin if(sel_reg[1] || sel_reg[3] || sel_reg[5] || sel_reg[7] || sel_reg[9] || sel_reg[11]) data_out <= pipe_ff[16:31]; else data_out <= pipe_ff[15:0] end end Также нужно не забыть дополнительно пропайплайнить все сигналы управления (strob, sel и т.д.), чтобы автомар раньше времени не вышел с состояния Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба Приветствую! 32 minutes ago, dimka76 said: Это интересно, но не понял сути идеи. Что именно должно быть на выходе предлагаемого вами декодера ? У вас 12 бит кодируют 8 состояний соответсвенно можно на такт раньше сделать предварительное кодирование ... // либо в bin reg [2:0] sel_r; case (sel) 12'b000000000001 : sel_r <= 3'd1; 12'b000000000100 : sel_r <= 3'd2; ... // на следующем такте case (sel_r) 3'd0: begin register[15:0] <= data_in_1[31:16]; data_out[15:0] <= data_in_1[15:0]; end ... // либо в onehot reg [7:0] sel_r; 12'b000000000001 : sel_r <= 1<<0; 12'b000000000100 : sel_r <= 1<<1; ... // на следующем такте case (1'b1) // synthesis parallel_case full_case sel_r[0]: begin register[15:0] <= data_in_1[31:16]; data_out[15:0] <= data_in_1[15:0]; end ... Удачи! Rob Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 42 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба 1 hour ago, RobFPGA said: У вас 12 бит кодируют 8 состояний соответсвенно можно на такт раньше сделать предварительное кодирование ...... У меня уже до этого обратное проедоленоого вами производится module addr_dec(clk, i_rst, addr, a_out) /* synthesis syn_romstyle = "EBR" */; input wire clk; input wire i_rst; input [3:0] addr; output wire [11:0] a_out; reg [11:0] out ; always @(posedge clk or posedge i_rst) begin if(i_rst) out <= 12'd0; else case(addr) 4'd0: out <= 12'b000000000001; 4'd1: out <= 12'b000000000010; 4'd2: out <= 12'b000000000100; 4'd3: out <= 12'b000000001000; 4'd4: out <= 12'b000000010000; 4'd5: out <= 12'b000000100000; 4'd6: out <= 12'b000001000000; 4'd7: out <= 12'b000010000000; 4'd8: out <= 12'b000100000000; 4'd9: out <= 12'b001000000000; 4'd10: out <= 12'b010000000000; 4'd11: out <= 12'b100000000000; default: out <= 12'b000000000000; endcase end assign a_out = out; endmodule И далее addr_dec AD1 ( .clk(clk_150), .i_rst(g_rst), .addr(addres[3:0]), .a_out(code)) /* synthesis syn_romstyle = "EBR" */; reg_mux RM1 ( .clk(clk_150), .i_rst(g_rst), .sel(code), .strob(rd_strobe), .data_in_1(quad_out_1), .data_in_2(quad_out_2), .data_in_3(quad_out_3), .z_in_1(z_out_1), .z_in_2(z_out_2), .z_in_3(z_out_3), .data_out(reg_out)); Наверное стоит убрать addr_dec AD1 (...), а addres[3:0]) напрямую заводить в reg_mux RM1 (....) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба ИМХО, вот такие перлы из-за того, что не читают хендбук на целевую ПЛИС, о том какие строительные кубики есть в этой песочнице) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба Приветствую! 11 minutes ago, dimka76 said: Наверное стоит убрать addr_dec AD1 (...), а addres[3:0]) напрямую заводить в reg_mux RM1 (....) Может быть. Тут надо понимать как наиболее оптимально реализуется mux на архитектуре вашей FPGA (в зависимости от размера и архитектуры LUT). Я с Lattice не работал поэтом точно не скажу - но есть 2 варианта либо классический бинарный mux - или ohehot AND/OR структура. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 42 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба 1 hour ago, Nick_K said: В этом месте было бы хорошо разделить на 2 процесса (читай вставить дополнительные промежуточные регистры): по чётным унарным сигналам захлопывать данные в промежуточный pipeline FF (ну или просто в промежуточный регистр), а уже по нечётным засовывать в выходной сдвиговый регистр. Что-то типа такого: Также нужно не забыть дополнительно пропайплайнить все сигналы управления (strob, sel и т.д.), чтобы автомар раньше времени не вышел с состояния Боюсь, что это может разойтись с логикой работы моего устройства. Да и все данные, которые здесь используются формируются внутри ПЛИС и привязаны к одному и тому же клоку. 5 minutes ago, des00 said: ИМХО, вот такие перлы из-за того, что не читают хендбук на целевую ПЛИС, о том какие строительные кубики есть в этой песочнице) Какие такие ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба 7 minutes ago, dimka76 said: Какие такие ? вы с латтисом работаете, вам и карты в руки .Полагаю что в документе LatticeXP2 Family Data Sheet - Architecture - PFU Blocks должны быть описаны основные кубики. А дальше, ваше сопоставление хотелок, строительным кубикам и вперед, делать оптимальный, для целевой плис, код. 1 hour ago, RobFPGA said: Удачи! Rob забыли еще AND-OR мультиплексор. техника древняя, но кое где рабочая) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Plain 168 25 июня, 2020 Опубликовано 25 июня, 2020 · Жалоба 1 час назад, dimka76 сказал: это может разойтись с логикой работы моего устройства Тогда лишь остаётся в явном виде описать коммутацию на 1-битных мультиплексорах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 26 июня, 2020 Опубликовано 26 июня, 2020 · Жалоба 18 hours ago, dimka76 said: Наверное стоит убрать addr_dec AD1 (...), а addres[3:0]) напрямую заводить в reg_mux RM1 (....) Скорее всего и оптимальнее, да. Symplify далеко не дурной синтезатор (может даже один из лучших, которіх я видел), сам сможет построить нужную логику, чтобы не далать лишние преобразования. Одним словом попробуйте описать проще все конструкции и посмотреть что будет, может синтезатор сам сможет разрулить и выдать толковую частоту. Нет, тогда уже смотреть критические пути и пайплайнить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lexx 0 26 июня, 2020 Опубликовано 26 июня, 2020 · Жалоба Перейдите на one hot. Это быстрее, чем текущий if-else. И сделайте констрейны на тактовой сигнал, синтезатор хотя бы попытается все это привести к нужному виду. Без настоящего клока, синтез только получит функцию, без каких-либо оптимизаций. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться