diwil 0 10 сентября, 2009 Опубликовано 10 сентября, 2009 · Жалоба Уважаемые, У меня такой вопрос - как в верилоге запихнуть заранее известные константы в память? Сейчас я делаю так: function signed [31:0] COEF(input [6:0] num) case (num) 0: COEF = 12312; 1: COEF = 45634; ... 127: COEF = 346523; endcase endfunction А потом в коде пишу что-то вроде такого: a <= b + COEF(x); Однако, у меня создается впечатление, что все эти константы квактус размещает в регистрах. Вопрос - как сделать так, чтобы они поместились в блоки памяти циклона? заранее благодарен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Artem_Petrik 0 10 сентября, 2009 Опубликовано 10 сентября, 2009 · Жалоба Квартус понимает (по крайней мере 7 версии) такое вот reg [7:0] mem [255:0]; initial mem = $readmem("mem_initialization_filename.mif"); За синтаксис не ручаюсь, проверить сейчас не на чем. Это вроде в мануале по квартусу упоминается, кажись в разделе "Синтез". Также можно сделать визардом память, и указать для нее HEX файл с инициализационной информацией. P.S. Вот нашел: http://www.altera.com/literature/hb/qts/qts_qii5v1_03.pdf страница 9-7 "Initial Constructs and Memory System Tasks" Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
diwil 0 10 сентября, 2009 Опубликовано 10 сентября, 2009 · Жалоба Квартус понимает (по крайней мере 7 версии) такое вот reg [7:0] mem [255:0]; initial mem = $readmem("mem_initialization_filename.mif"); За синтаксис не ручаюсь, проверить сейчас не на чем. Это вроде в мануале по квартусу упоминается, кажись в разделе "Синтез". Также можно сделать визардом память, и указать для нее HEX файл с инициализационной информацией. P.S. Вот нашел: http://www.altera.com/literature/hb/qts/qts_qii5v1_03.pdf страница 9-7 "Initial Constructs and Memory System Tasks" квартус умирает так... ладно... буду пробовать. спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sazh 3 10 сентября, 2009 Опубликовано 10 сентября, 2009 · Жалоба ладно... буду пробовать. спасибо. COEF через регистр пропустите. Должен тогда в память положить автоматом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
diwil 0 11 сентября, 2009 Опубликовано 11 сентября, 2009 · Жалоба COEF через регистр пропустите. Должен тогда в память положить автоматом. не ложет, зараза... вот код... в нем хотелось бы заменить функцию на что-либо более читаемое... кажый инклюд содержит строки типа: 0: COEF = ... 1: COEF = ... 127: COEF = module fir128 #( // Parameter Declarations parameter INPUT_WIDTH = 32, // these two parameter COEF_WIDTH = 32, // must be equal parameter OUTPUT_WIDTH = 16, parameter ACC_WIDTH = 64, parameter DLENGTH = 128 ) ( // Input Ports input clk10, input in_latch, input reset_n, input signed [INPUT_WIDTH-1:0] data_i, input signed [INPUT_WIDTH-1:0] data_q, input [1:0] coef_set, // Output Ports output reg data_valid, output reg [OUTPUT_WIDTH-1:0] data_out_i, output reg [OUTPUT_WIDTH-1:0] data_out_q ); (* ramstyle = "M9K" *) reg signed [INPUT_WIDTH-1:0] delay_i [DLENGTH-1:0]; (* ramstyle = "M9K" *) reg signed [INPUT_WIDTH-1:0] delay_q [DLENGTH-1:0]; reg signed [ACC_WIDTH-1:0] acc_i, acc_q; reg signed [INPUT_WIDTH-1:0] dnext_i, dnext_q; reg signed [INPUT_WIDTH-1:0] cnext; reg [6:0] rd_addr, wr_addr, ccnt; reg latched; // to avoid overflow: wire [OUTPUT_WIDTH-1:0] acc_final_i, acc_final_q; assign acc_final_i = acc_i[ACC_WIDTH-2: ACC_WIDTH-OUTPUT_WIDTH-1]; assign acc_final_q = acc_q[ACC_WIDTH-2: ACC_WIDTH-OUTPUT_WIDTH-1]; integer i; initial begin acc_i <= 0; acc_q <= 0; rd_addr <= 0; wr_addr <= 0; latched <= 0; data_valid <= 0; ccnt <= 0; for (i=0; i<128; i = i + 1) begin delay_i[i] <= 0; delay_q[i] <= 0; end end function signed [INPUT_WIDTH-1:0] COEF(input [6:0] num); // Optional Block Declarations case (coef_set) 2'b00: begin case(num) 0: COEF = 1*(2**(COEF_WIDTH-1)-1); default: COEF = 0; endcase end 2'b01: begin case (num) `include "coef0001.v" default: COEF = 0; endcase end 2'b10: begin case (num) `include "coef15.v" default: COEF = 0; endcase end 2'b11: begin case (num) `include "coef15fm.v" default: COEF = 0; endcase end endcase endfunction always @(posedge clk10) begin if (reset_n == 0) begin acc_i <= 0; acc_q <= 0; rd_addr <= 0; wr_addr <= 0; latched <= 0; data_valid <= 0; ccnt <= 0; end else if (!latched && in_latch == 1'b1) begin acc_i <= 0; acc_q <= 0; latched <= 1; data_valid <= 0; dnext_i <= data_i; dnext_q <= data_q; cnext <= COEF(0); delay_i[wr_addr] <= data_i; delay_q[wr_addr] <= data_q; rd_addr <= wr_addr - 1; wr_addr <= wr_addr + 1; ccnt <= 1; end else if (latched) begin acc_i <= acc_i + dnext_i * cnext; acc_q <= acc_q + dnext_q * cnext; dnext_i <= delay_i[rd_addr]; dnext_q <= delay_q[rd_addr]; rd_addr <= rd_addr - 1; cnext <= COEF(ccnt); ccnt <= ccnt + 1; if (ccnt == 0) begin data_valid <= 1; latched <= 0; ///------------------------- AVOID OVERFLOW - SATURATE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! data_out_i <= acc_final_i + ((acc_final_i != 16'h7fff) ? acc_i[ACC_WIDTH-OUTPUT_WIDTH-2] : 0); data_out_q <= acc_final_q + ((acc_final_q != 16'h7fff) ? acc_q[ACC_WIDTH-OUTPUT_WIDTH-2] : 0); end end // end if end endmodule Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Artem_Petrik 0 11 сентября, 2009 Опубликовано 11 сентября, 2009 · Жалоба вот код... в нем хотелось бы заменить функцию на что-либо более читаемое... Вы хотите, чтобы COEF был памятью. Так и описывайте его как память! Вы delay_i и delay_q ведь описали как память, вот и с коэффициентами поступите также. reg [31:0] coeff [127:0]; initial begin coef[0] = .... coef[1] = ... ... coef[127] = ... end либо с использованием $readmemb (не знаю, что значит умирает, у меня работало без проблем.) Если у Вас не будет попыток читать эту память асинхронно (а в приведенном исходнике этого вроде нет), то все будет с радостью упаковываться в блочную память. В конце концов, попробуйте написать модуль, в котором только ПЗУ, меньше букв - проще найти причину поведения синтезатора. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sazh 3 11 сентября, 2009 Опубликовано 11 сентября, 2009 · Жалоба не ложет, зараза... Я хотел сказать, что такое на 128 ячеект точно в память упакует ( input clk, input [7:0] addr, output reg [15:0] cos_sin ); always @ (posedge clk) begin case (addr) 8'h00: cos_sin = 16'h7f00; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 11 сентября, 2009 Опубликовано 11 сентября, 2009 · Жалоба включите режим SV и опишите память. а еше лучше mif файл сделайте и поставте black-box ЗЫ. не всегда квартус видит смысл ложить ром в память, если константы простые, то он может сделать все на логике. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kopart 0 13 сентября, 2009 Опубликовано 13 сентября, 2009 · Жалоба Я хотел сказать, что такое на 128 ячеект точно в память упакует ( input clk, input [7:0] addr, output reg [15:0] cos_sin ); always @ (posedge clk) begin case (addr) 8'h00: cos_sin = 16'h7f00; Для автора вопроса уточняю: в этом примере нет инициализации по ресету. И это так и должно быть! Квартус автоматом кладет в память начиная с 33 адресов. Но изменив параметр в меню - можно запихнуть в память и меньше адресов. А то ругается, что память маленькая - делаю на регистрах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
diwil 0 14 сентября, 2009 Опубликовано 14 сентября, 2009 · Жалоба чего-то нихрена не получается... серано как не крути фсе ложет на регистры. На регистрах занимает около 1500 ле. хм... чего-то нихрена не получается... серано как не крути фсе ложет на регистры. На регистрах занимает около 1500 ле. хм... И еще квартус говорит так: Internal Error: Sub-system: VRFX, File: /quartus/synth/vrfx/verific/verilog/veriname_elab.cpp, Line: 879 read to RAM wasn't mapped to a specific read port Stack Trace: 0xE4F99 : VRFX_ELABORATOR::elaborate + 0x9DA09 (synth_vrfx) 0x80B5 : MEM_SEGMENT_INTERNAL::allocate + 0x95 (ccl_mem) End-trace Quartus II Version 9.0 Build 235 06/17/2009 SJ Web Edition Service Pack Installed: 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
diwil 0 14 сентября, 2009 Опубликовано 14 сентября, 2009 · Жалоба F вот для такого кода - // altera message_off 10030 module dir128 #( // Parameter Declarations parameter INPUT_WIDTH = 32, // these two parameter COEF_WIDTH = 32, // must be equal parameter OUTPUT_WIDTH = 32, parameter ACC_WIDTH = 64, parameter DLENGTH = 128) ( // Input Ports input clk10, input [1:0] coef_set, input [6:0] cnt, input reset_n, output reg [OUTPUT_WIDTH-1:0] data_out_i); (* ramstyle = "M9K" *) reg signed [INPUT_WIDTH-1:0] coef1 [0:DLENGTH-1]; (* ramstyle = "M9K" *) reg signed [INPUT_WIDTH-1:0] coef2 [0:DLENGTH-1]; (* ramstyle = "M9K" *) reg signed [INPUT_WIDTH-1:0] coef3 [0:DLENGTH-1]; initial begin $readmemh("coef0.lst",coef1); $readmemh("coef1.txt",coef2); $readmemh("coef2.txt",coef3); end always @(posedge clk10) begin case (coef_set) 0: data_out_i <= (cnt == 6'b0) ? 32'h7fffffff : 32'h0; 1: data_out_i <= coef1[cnt]; 2: data_out_i <= coef2[cnt]; 3: data_out_i <= coef3[cnt]; endcase end endmodule Почему-то вообще странные вещи происходят: 1. Quartus ругается так: Info: Found 3 instances of uninferred RAM logic Info: RAM logic "coef1" is uninferred due to asynchronous read logic Info: RAM logic "coef2" is uninferred due to asynchronous read logic Info: RAM logic "coef3" is uninferred due to asynchronous read logic 2. После компиляции он не показывает, что используется память. 3. Временная симуляция дает бредовый результат, если 'cnt' переходит из 127 в 0 4. Функциональная вроде хорошо. НО!!! возникает вопрос - куда квартус складывает константы??? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 14 сентября, 2009 Опубликовано 14 сентября, 2009 · Жалоба always @(posedge clk10) begin case (coef_set) 0: data_out_i <= (cnt == 6'b0) ? 32'h7fffffff : 32'h0; 1: data_out_i <= coef1[cnt]; 2: data_out_i <= coef2[cnt]; 3: data_out_i <= coef3[cnt]; endcase end endmodule Почему-то вообще странные вещи происходят: 1. Quartus ругается так: Info: Found 3 instances of uninferred RAM logic Info: RAM logic "coef1" is uninferred due to asynchronous read logic Info: RAM logic "coef2" is uninferred due to asynchronous read logic Info: RAM logic "coef3" is uninferred due to asynchronous read logic абсолютно правильно ругается, нет у него памяти с асинхронным чтением, о чем он вас и предупреждает. из вашего кода это же очевидно. на 1 регистр у вас приходиться 3 блока памяти + мультиплексор 3в1. Куда по вашему он должен ставить этот мультиплексор ? что бы упахал в память надо было писать так : always @(posedge clk10) begin data_out_i_init <= (cnt == 6'b0) ? 32'h7fffffff : 32'h0; data_out_i_ram1 <= coef1[cnt]; data_out_i_ram2 <= coef2[cnt]; data_out_i_ram3 <= coef3[cnt]; end always @(*) begin case (coef_set) 0: data_out_i = data_out_i_init; 1: data_out_i = data_out_i_ram1; 2: data_out_i = data_out_i_ram2; 3: data_out_i = data_out_i_ram3; endcase end Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
diwil 0 14 сентября, 2009 Опубликовано 14 сентября, 2009 · Жалоба абсолютно правильно ругается, нет у него памяти с асинхронным чтением, о чем он вас и предупреждает. из вашего кода это же очевидно. на 1 регистр у вас приходиться 3 блока памяти + мультиплексор 3в1. Тогда такой вопрос (а то я совсем запутался ...) Если я выделяю памяти в 4 раза больше (длина вся 512 элементов): (* ramstyle = "M9K" *) reg signed [iNPUT_WIDTH-1:0] coeffs [0 : DLENGTH*4-1]; потом формирую адрес для чтения как cra = {coeff_set,ccnt} (всего 9 бит) и потом по защелке (и по clk10) читаю: cnext <= coeffs[cra]; ccnt <= 1; и далее по клоку clk10 : cnext <= coeffs[cra]; ccnt <= ccnt + 1; то получается тоже бред - квартус выкидывает биты cnext и вообще получаются не правильные коэффициенты. Где я ошибся? wire [8:0] cread_address; assign cread_address = {coef_set,ccnt}; always @(posedge clk10) begin if (reset_n == 0) begin acc_i <= 0; acc_q <= 0; rd_addr <= 0; wr_addr <= 0; latched <= 0; data_valid <= 0; ccnt <= 0; // $readmemh("coeffs.txt", coeffs); end else if (!latched && in_latch == 1'b1) begin acc_i <= 0; acc_q <= 0; latched <= 1; data_valid <= 0; dnext_i <= data_i; dnext_q <= data_q; cnext <= coeffs[cread_address]; // should be always zero delay_i[wr_addr] <= data_i; delay_q[wr_addr] <= data_q; rd_addr <= wr_addr - 1; wr_addr <= wr_addr + 1; ccnt <= 1; end else if (latched) begin acc_i <= acc_i + dnext_i * cnext; acc_q <= acc_q + dnext_q * cnext; dnext_i <= delay_i[rd_addr]; dnext_q <= delay_q[rd_addr]; rd_addr <= rd_addr - 1; cnext <= coeffs[cread_address]; ccnt <= ccnt + 1; if (ccnt == 0) begin data_valid <= 1; latched <= 0; ///------------------------- AVOID OVERFLOW - SATURATE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! data_out_i <= acc_final_i + ((acc_final_i != 16'h7fff) ? acc_i[ACC_WIDTH-OUTPUT_WIDTH-2] : 0); data_out_q <= acc_final_q + ((acc_final_q != 16'h7fff) ? acc_q[ACC_WIDTH-OUTPUT_WIDTH-2] : 0); end end // end if end Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 15 сентября, 2009 Опубликовано 15 сентября, 2009 · Жалоба Тогда такой вопрос (а то я совсем запутался ...) тогда бы уж весь код выкладывали, что бы можно было его собрать в ква. Вот вам пример FIRa на памяти module fir_ram #( parameter int pID_W = 18, parameter int pOD_W = 18 ) ( iclk , ival , idat , oval , odat ); //------------------------------------------------------------------------------------------------------ // //------------------------------------------------------------------------------------------------------ input logic iclk ; input logic ival ; input logic [pID_W-1 : 0] idat ; output logic oval ; output logic [pOD_W-1 : 0] odat ; //------------------------------------------------------------------------------------------------------ // //------------------------------------------------------------------------------------------------------ localparam int cC_W = 18; localparam int cACC_W = pID_W + cC_W; typedef logic signed [pID_W-1 : 0] dat_t; typedef logic signed [cC_W-1 : 0] coe_t; typedef logic signed [cACC_W-1 : 0] acc_t; localparam coe_t cCOE [0 : 63] = '{ 58, -12, -115, -183, -139, 43, 285, 419, 281, -151, -663, -875, -482, 463, 1433, 1665, 674, -1233, -2904, -2930, -666, 2979, 5679, 4960, 15, -7078, -11781, -9280, 2613, 21542, 41050, 53404, 53404, 41050, 21542, 2613, -9280, -11781, -7078, 15, 4960, 5679, 2979, -666, -2930, -2904, -1233, 674, 1665, 1433, 463, -482, -875, -663, -151, 281, 419, 285, 43, -139, -183, -115, -12, 58 }; logic [6 : 0] cnt; logic cycle_done; logic [5 : 0] wptr; logic [5 : 0] rptr; logic sop, eop, val, done; dat_t dat [0 : 63] ; dat_t dat2mult /*synthesis ramstyle = "M4K, no_rw_check"*/; coe_t coe2mult /*synthesis ramstyle = "M4K, no_rw_check"*/; acc_t mult; acc_t acc; //------------------------------------------------------------------------------------------------------ // //------------------------------------------------------------------------------------------------------ // synthesis translate_off initial begin : ini cnt = 7'h40; wptr = '0; rptr = '0; dat = '{default : 0}; dat2mult = '0; coe2mult = '0; acc = '0; oval = '0; done = '0; end // synthesis translate_on //------------------------------------------------------------------------------------------------------ // //------------------------------------------------------------------------------------------------------ assign cycle_done = cnt [6]; always_ff @(posedge iclk) begin if (ival) begin cnt <= '0; wptr <= wptr + 1'b1; rptr <= wptr; dat[wptr] <= idat; end else if (!cycle_done) begin cnt <= cnt + 1'b1; coe2mult <= cCOE[cnt]; rptr <= rptr - 1'b1; dat2mult <= dat[rptr]; end sop <= !(|cnt[5:0]); val <= !(cycle_done); eop <= (&cnt[5:0]); // end assign mult = dat2mult * coe2mult; always_ff @(posedge iclk) begin done <= eop; if (sop) acc <= mult; else if (val) acc <= acc + mult; oval <= done; if (done) odat <= acc[cACC_W-1 : cACC_W - pOD_W]; end endmodule // synthesis translate_off module tb ; parameter int pID_W = 18 ; parameter int pOD_W = 19 ; logic iclk ; logic ival ; logic [pOD_W-1 : 0] idat ; logic oval ; logic [pOD_W-1 : 0] odat ; fir_ram #( .pID_W ( pID_W ) , .pOD_W ( pOD_W ) ) fir_ram ( .iclk ( iclk ) , .ival ( ival ) , .idat ( idat ) , .oval ( oval ) , .odat ( odat ) ); initial begin : ini iclk <= 1'b0; #5ns forever #5ns iclk = ~iclk; end initial begin : main ival <= '0; idat <= '0; repeat (2) @(posedge iclk); for (int i = 0; i < 128; i++) begin int data; data = (i == 64)*(2**(pID_W-1)-1); set_data(data); end repeat (63) set_data(0); $stop; end task set_data (input int data ); ival <= 1'b1; idat <= data; @(posedge iclk); ival <= 1'b0; repeat (63) @(posedge iclk); endtask endmodule // synthesis translate_on результат синтеза в ква Resource Usage Total logic elements 96 / 24,624 ( < 1 % ) -- Combinational with no register 18 -- Register only 20 -- Combinational with a register 58 Logic element usage by number of LUT inputs -- 4 input functions 2 -- 3 input functions 49 -- <=2 input functions 25 -- Register only 20 Logic elements by mode -- normal mode 26 -- arithmetic mode 50 Total registers* 78 / 24,964 ( < 1 % ) -- Dedicated logic registers 78 / 24,624 ( < 1 % ) -- I/O registers 0 / 340 ( 0 % ) Total LABs: partially or completely used 7 / 1,539 ( < 1 % ) User inserted logic elements 0 Global signals 1 M9Ks 2 / 66 ( 3 % ) Total block memory bits 2,240 / 608,256 ( < 1 % ) Total block memory implementation bits 18,432 / 608,256 ( 3 % ) Embedded Multiplier 9-bit elements 2 / 132 ( 2 % ) дальше думаю разберетесь :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться