§ Главный шаблон
Скачать весь шаблон можно тут.module max2 ( input clock, input [3:0] key, inout [7:0] led, inout [9:0] f0, inout [9:0] f1, inout [9:0] f2, inout [9:0] f3, inout [9:0] f4, inout [9:0] f5, inout dp, inout dn, inout pt ); assign f0 = 10'hz; assign f1 = 10'hz; assign f2 = 10'hz; assign f3 = 10'hz; assign f4 = 10'hz; assign f5 = 10'hz; wire [15:0] datain; wire ready; altufm_reader UFMReaderUnit ( .osc (osc), .address (9'h1), .datain (datain), .ready (ready) ); endmodule
§ Блок AltUFM
Этот блок инициализирует физический модуль ufm.//synopsys translate_off `timescale 1 ps / 1 ps //synopsys translate_on module altufm ( input arclk, // Запись на позитивном фронте АДРЕС input ardin, // Входящий бит адреса (MSB), первый бит старший input arshft, // =1 последовательная загрузка адреса, =0 то +1 к адресу output busy, // =1 Устройство занято input drclk, // Запись на позитивном фронте ДАННЫХ input drdin, // Входящие бит MSB output drdout, // Исходящий бит MSB input drshft, // =0 @posedge drclk, копирование из/в UFM, =1 вдвиг бита input erase, // =1 очистить блок output osc, // Тактовый осциллятор ~ 5.5 Мгц input oscena, // =1 Разрешение тактового генератора input program, // =1 Программирование UFM output rtpbusy // =1 Устройство занято программированием ); maxii_ufm maxii_ufm_block1 ( .arclk (arclk), .ardin (ardin), .arshft (arshft), .bgpbusy (rtpbusy), .busy (busy), .drclk (drclk), .drdin (drdin), .drdout (drdout), .drshft (drshft), .erase (erase), .osc (osc), .oscena (oscena), .program (program), // synopsys translate_off .ctrl_bgpbusy (1'b0), .devclrn (1'b1), .devpor (1'b1), .sbdin (1'b0), .sbdout () // synopsys translate_on ); defparam maxii_ufm_block1.address_width = 9, maxii_ufm_block1.erase_time = 500000000, maxii_ufm_block1.init_file = "ufm.mif", // Копия тестовых данных 1Кб maxii_ufm_block1.mem1 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem2 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem3 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem4 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem5 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem6 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem7 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem8 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem9 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem10 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem11 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem12 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem13 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem14 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem15 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.mem16 = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, maxii_ufm_block1.osc_sim_setting = 180000, maxii_ufm_block1.program_time = 1600000, maxii_ufm_block1.lpm_type = "maxii_ufm"; endmodule
§ Работа с UFM
Когда приходит сигнал ready, тогда можно установить новый адрес сразу же и получить данные.Top-уровень
wire [15:0] datain; wire ready; altufm_reader UFMReaderUnit ( .osc (osc), .address (9'h1), .datain (datain), .ready (ready) );Модуль считывания
module altufm_reader ( output osc, // Осциллятор input [8:0] address, // Заданный адрес output reg [15:0] datain, // Полученные данные output ready // Признак готовности данных ); assign ready = (cnt == 27); reg [4:0] cnt = 1'b0; reg ardin = 1'b0; reg drshft = 1'b0; wire drdout; altufm AltUFMUnit ( .arclk (osc), .drclk (osc), .drdin (1'b0), // Данные для программирования Flash .drdout (drdout), // Выходные данные .drshft (drshft), // 0: Защелка, 1: Задвижка .ardin (ardin), // Данные для адреса .arshft (1'b1), // Всегда последовательный адрес .oscena (1'b1), // Активировать осциллятор .osc (osc) // Осциллятор 5.56 Мгц ); always @(posedge osc) begin cnt <= cnt + 1; drshft <= cnt > 9; ardin <= cnt < 9 ? address[8 - cnt] : 1'b0; datain <= {datain[14:0], drdout}; // Данные готовы if (ready) cnt <= 0; end endmodule
§ Эмулятор UFM
Здесь osc — это input-провод, поскольку osc задается в tb.vmodule altufm ( input wire oscena, input wire osc, input wire arclk, input wire ardin, input wire arshft, input wire drclk, input wire drdin, input wire drshft, output wire drdout, input wire prgram ); // --------------------------------------------------------------------- reg [15:0] ufm[512]; initial begin $readmemh("ufm.hex", ufm, 0); end // --------------------------------------------------------------------- assign drdout = datareg[15]; // 512 x 16 = 1024 байт памяти reg [ 8:0] address; reg [15:0] datareg; // Вдвиг адреса или увеличение на +1 always @(posedge arclk) address <= arshft ? {address[7:0], ardin} : address + 1; always @(posedge drclk or posedge prgram) if (prgram) ufm[address] <= datareg; else if (drshft) datareg <= {datareg[14:0], drdin}; else datareg <= ufm[address]; endmodule