§ Главный шаблон

Скачать весь шаблон можно тут.
1module max2
2(
3    input           clock,
4    input   [3:0]   key,
5    inout   [7:0]   led,
6    inout   [9:0]   f0,
7    inout   [9:0]   f1,
8    inout   [9:0]   f2,
9    inout   [9:0]   f3,
10    inout   [9:0]   f4,
11    inout   [9:0]   f5,
12    inout           dp,
13    inout           dn,
14    inout           pt
15);
16
17assign f0 = 10'hz; assign f1 = 10'hz; assign f2 = 10'hz;
18assign f3 = 10'hz; assign f4 = 10'hz; assign f5 = 10'hz;
19
20wire [15:0] datain;
21wire        ready;
22
23altufm_reader UFMReaderUnit
24(
25    .osc        (osc),
26    .address    (9'h1),
27    .datain     (datain),
28    .ready      (ready)
29);
30
31endmodule

§ Блок AltUFM

Этот блок инициализирует физический модуль ufm.
1//synopsys translate_off
2`timescale 1 ps / 1 ps
3
4//synopsys translate_on
5module altufm
6(
7    input   arclk,      // Запись на позитивном фронте АДРЕС
8    input   ardin,      // Входящий бит адреса (MSB), первый бит старший
9    input   arshft,     // =1 последовательная загрузка адреса, =0 то +1 к адресу
10    output  busy,       // =1 Устройство занято
11    input   drclk,      // Запись на позитивном фронте ДАННЫХ
12    input   drdin,      // Входящие бит MSB
13    output  drdout,     // Исходящий бит MSB
14    input   drshft,     // =0 @posedge drclk, копирование из/в UFM, =1 вдвиг бита
15    input   erase,      // =1 очистить блок
16    output  osc,        // Тактовый осциллятор ~ 5.5 Мгц
17    input   oscena,     // =1 Разрешение тактового генератора
18    input   program,    // =1 Программирование UFM
19    output  rtpbusy     // =1 Устройство занято программированием
20);
21
22maxii_ufm maxii_ufm_block1
23(
24    .arclk          (arclk),
25    .ardin          (ardin),
26    .arshft         (arshft),
27    .bgpbusy        (rtpbusy),
28    .busy           (busy),
29    .drclk          (drclk),
30    .drdin          (drdin),
31    .drdout         (drdout),
32    .drshft         (drshft),
33    .erase          (erase),
34    .osc            (osc),
35    .oscena         (oscena),
36    .program        (program),
37    // synopsys translate_off
38    .ctrl_bgpbusy   (1'b0),
39    .devclrn        (1'b1),
40    .devpor         (1'b1),
41    .sbdin          (1'b0),
42    .sbdout         ()
43    // synopsys translate_on
44);
45
46defparam
47    maxii_ufm_block1.address_width   = 9,
48    maxii_ufm_block1.erase_time      = 500000000,
49    maxii_ufm_block1.init_file       = "ufm.mif",
50    // Копия тестовых данных 1Кб
51    maxii_ufm_block1.mem1            = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
52    maxii_ufm_block1.mem2            = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
53    maxii_ufm_block1.mem3            = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
54    maxii_ufm_block1.mem4            = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
55    maxii_ufm_block1.mem5            = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
56    maxii_ufm_block1.mem6            = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
57    maxii_ufm_block1.mem7            = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
58    maxii_ufm_block1.mem8            = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
59    maxii_ufm_block1.mem9            = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
60    maxii_ufm_block1.mem10           = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
61    maxii_ufm_block1.mem11           = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
62    maxii_ufm_block1.mem12           = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
63    maxii_ufm_block1.mem13           = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
64    maxii_ufm_block1.mem14           = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
65    maxii_ufm_block1.mem15           = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
66    maxii_ufm_block1.mem16           = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
67    maxii_ufm_block1.osc_sim_setting = 180000,
68    maxii_ufm_block1.program_time    = 1600000,
69    maxii_ufm_block1.lpm_type        = "maxii_ufm";
70
71endmodule

§ Работа с UFM

Когда приходит сигнал ready, тогда можно установить новый адрес сразу же и получить данные.
Top-уровень
1wire [15:0] datain;
2wire        ready;
3
4altufm_reader UFMReaderUnit
5(
6    .osc        (osc),
7    .address    (9'h1),
8    .datain     (datain),
9    .ready      (ready)
10);
Модуль считывания
1module altufm_reader
2(
3    output              osc,            // Осциллятор
4    input        [8:0]  address,        // Заданный адрес
5    output  reg  [15:0] datain,         // Полученные данные
6    output              ready           // Признак готовности данных
7);
8
9assign      ready = (cnt == 27);
10reg [4:0]   cnt     = 1'b0;
11reg         ardin   = 1'b0;
12reg         drshft  = 1'b0;
13wire        drdout;
14
15altufm AltUFMUnit
16(
17    .arclk  (osc),
18    .drclk  (osc),
19    .drdin  (1'b0),     // Данные для программирования Flash
20    .drdout (drdout),   // Выходные данные
21    .drshft (drshft),   // 0: Защелка, 1: Задвижка
22    .ardin  (ardin),    // Данные для адреса
23    .arshft (1'b1),     // Всегда последовательный адрес
24    .oscena (1'b1),     // Активировать осциллятор
25    .osc    (osc)       // Осциллятор 5.56 Мгц
26);
27
28always @(posedge osc)
29begin
30
31    cnt    <= cnt + 1;
32    drshft <= cnt > 9;
33    ardin  <= cnt < 9 ? address[8 - cnt] : 1'b0;
34    datain <= {datain[14:0], drdout};
35
36    // Данные готовы
37    if (ready) cnt <= 0;
38
39end
40
41endmodule

§ Эмулятор UFM

Здесь osc — это input-провод, поскольку osc задается в tb.v
1module altufm
2(
3    input   wire    oscena,
4    input   wire    osc,
5
6    input   wire    arclk,
7    input   wire    ardin,
8    input   wire    arshft,
9
10    input   wire    drclk,
11    input   wire    drdin,
12    input   wire    drshft,
13    output  wire    drdout,
14
15    input   wire    prgram
16);
17
18// ---------------------------------------------------------------------
19reg [15:0] ufm[512];
20initial begin $readmemh("ufm.hex", ufm, 0); end
21// ---------------------------------------------------------------------
22
23assign drdout = datareg[15];
24
25// 512 x 16 = 1024 байт памяти
26reg [ 8:0] address;
27reg [15:0] datareg;
28
29// Вдвиг адреса или увеличение на +1
30always @(posedge arclk)
31    address <= arshft ? {address[7:0], ardin} : address + 1;
32
33always @(posedge drclk or posedge prgram)
34if (prgram)
35    ufm[address] <= datareg;
36else if (drshft)
37    datareg <= {datareg[14:0], drdin};
38else
39    datareg <= ufm[address];
40
41endmodule