Yuri Panchul (panchul) wrote,
Yuri Panchul
panchul

Написал примерчик на верилоге для начинающих - стековый калькулятор

Господа! Как вы знаете, я вместе с другими товарищами консультирую Антона Моисеева и Андрея Маклакова, сотрудников кафедры прикладной математики Нижегородского государственного технического университета ( http://www.nntu.ru ), которые создают экспериментальный курс основ проектирования электроники для программистов.

Журнал Антона Моисеева, специально созданный для освещения темы - http://1i7.livejournal.com
Мои посты по теме - http://panchul.livejournal.com/tag/nntu

Студенты Антона Моисеева уже поигрались с микросхемами малой степени интеграции, что в свое время вызвало негодование ЖЖ-юзера uzhas_sovka. Ужас наверное сам бы с удовольствием потыкал проводками в макетную плату, но после учебы в пижонском университете Чикаго uzhas_sovka боится, что его застанут за этим занятием нобелевские лауреаты по экономике и выдавят из своего круга, чисто из-за зависти.

После игрищ с микросхемами серии 4000, студенты Моисеева пересели на Xilinx FPGA, научились описывать простейшие комбинаторные цепи на Верилоге и познакомились с концепциями RS-триггера и D-триггера. Пора задизайнить что-нибудь полезное.

Фото справа - спутник, внутри которого стоит Xilinx FPGA, взято с http://www.eetimes.com/design/military-aerospace-design/4216480/High-performance-FPGAs-take-flight-in-microsatellites

По этому поводу я написал примерчик стекового калькулятора и имплементировал его в плате Digilent Basys 2 c Xilinx Spartan 3E. Примерчик иллюстрирует модульность, конечные автоматы, регистровые файлы в Верилоге, а также содержит всякие полезные штучки для начинающих пользователей FPGA - clock divider, button debouncer, 7-segment display driver.

Калькуратор работает по принципу микрокалькулятора МК-54, который помнят советские школьники физматшкол 1980-х. Имеется стек, в котором хранятся числа. 8-битные числа вводятся с помощью рычажков, которые ненавидит ЖЖ-юзер exler. Текущая верхушка стека светится как 16-битное шестнадцатеричное число. Имеются четыре круглые кнопочки - reset, enter, add (+), multiply (*).

reset все обнуляет
enter вводит 8-битное число с рычажков в верхушку стека
add (+) удаляет два числа из верхушки стека, складывает их и вставляет в стек результат
multiply (*) удаляет два числа из верхушки стека, умножает их и вставляет в стек результат

Видите рычажки на плате справа? Это те самые, которых боится Экслер. А FPGA на этой же плате - той же компании, что и FPGA в британском спутнике.

Имеются две версии калькулятора - одна (calculator) с более-менее правильным стилем, принятым у RTL-дизайнеров, другая (calculator_behavioral) - с стилем, которым хардверные люди как правило не пишут, но который более понятен софтверным людям - код выглядит как последовательная программа, описывающая поведение дизайна во время одного цикла синхросигнала.

Причин, по которым хардверные люди не пишут как в calculator_behavioral, несколько, в частности:

1. В таком коде трудно понять, какой из верилоговских регистров в процессе синтеза превратится в D-триггер, а какой просто становится проводом

2. В таком коде трудно понять, как оптимизировать тайминг

3. Такой стиль может порождать трудно-отлаживаемые ошибки из категории race conditions если человек, который его пишет не очень аккуратен с blocking и non-blocking assignmnets.

Поэтому хардвер-дизайнеры пишут как в calculator - так чтобы в частности в комбинаторном always-блоке не возникало никаких защелок (об этом сигнализирует synthesis tool), а все D-триггеры появлялись явной форме, как переменные, которым присваивается значение в небольшом блоке always @(posedge clock), который не содержит вычисления никаких формул.

Еще у чисто софтверных людей может возникнуть вопрос, почему я для стека сдвигаю весь массив, а не просто указатель на верхушку стека. Это, братцы, вся фишка хардвера - параллельный сдвиг не очень большого массива флип-флопов дешевле, чем гиганский мультиплексор для его индексации.

Мы на эти темы еще поговорим, а пока я выкладываю все файлы своего примерчика, сопровождая их сиськами Mirelle A по наводке kpt_flint для выработки положительных ассоциаций у всех читателей моего журнала мужского пола. А Наталия Радулова может получать положительные ассоциации от созерцания моего юзерпика (она когда-то писала, но потом стерла, что я доставляю ей удовольствие).

При использовании нетривиального количества моего кода ссылка на меня (Юрий Панчул) обязательна. Понятно, что я не буду карать презрением за какой-то дурацкий дебаунсер на 10 строк (дебаунсеры уже давно общие, я его сам где-то спер), но меня не устроит, если какая-нибудь Дарья Донцова спионерит мой примерчик целиком, а потом ко мне будут прибегать идиоты и настаивать, что это я якобы спионерил у Дарьи Донцовой.

//-------------------------------------------------------------------------//
//
//  calculator.v
//
//-------------------------------------------------------------------------//

module calculator
(
    input         clock,
    input         reset,
    input         enter,
    input         add,
    input         multiply,
    input  [ 7:0] data,
    output [15:0] result,
    output        overflow,
    output [ 3:0] error
);

    assign error = 0;

    reg  [15:0] alu_a;
    reg  [15:0] alu_b;
    reg         alu_multiply;
    wire [15:0] alu_result;
    wire        alu_overflow;

    alu alu
    (
        .a          ( alu_a        ),
        .b          ( alu_b        ),
        .multiply   ( alu_multiply ),
        .result     ( alu_result   ),
        .overflow   ( alu_overflow )
    );

    reg r_overflow;
    assign overflow = r_overflow;

    always @(posedge clock)
    begin
        if (reset)
            r_overflow <= 0;
        else
            r_overflow <= alu_overflow;
    end

    reg         stack_push;
    reg         stack_pop;
    reg  [15:0] stack_write_data;
    wire [15:0] stack_read_data;

    stack stack
    (
        .clock      ( clock            ),
        .reset      ( reset            ),
        .push       ( stack_push       ),
        .pop        ( stack_pop        ),
        .write_data ( stack_write_data ),
        .read_data  ( stack_read_data  ) 
    );

    assign result = stack_read_data;

    reg  [15:0] r_alu_a;
    reg  [15:0] r_alu_b;
    reg         r_alu_multiply;
    reg  [ 1:0] state;

    reg  [ 1:0] next_state;

    always @(*)
    begin
        alu_a            = r_alu_a;
        alu_b            = r_alu_b;
        alu_multiply     = r_alu_multiply;
        stack_push       = 0;
        stack_pop        = 0;
        stack_write_data = data;
        next_state       = state;

        case (state)
        0:
           if (enter)
           begin
               stack_push       = 1;
               stack_write_data = data;
           end
           else if (add | multiply)
           begin
               alu_a            = stack_read_data;
               alu_multiply     = multiply;

               stack_pop        = 1;
               next_state       = 1;
           end

        1:
           begin
               alu_b            = stack_read_data;
               stack_pop        = 1;
               next_state       = 2;
           end

        2:
           begin
               stack_push       = 1;
               stack_write_data = alu_result;
               next_state       = 0;
           end

        endcase
    end

    always @(posedge clock)
    begin
        if (reset)
        begin
            r_alu_a        <= 0;
            r_alu_b        <= 0;
            r_alu_multiply <= 0;
            state          <= 0;
        end
        else
        begin
            r_alu_a        <= alu_a;
            r_alu_b        <= alu_b;
            r_alu_multiply <= alu_multiply;
            state          <= next_state;
        end
    end

endmodule



//-------------------------------------------------------------------------//
//
//  calculator_behavioral.v
//
//-------------------------------------------------------------------------//

`include "defines.vh"

module calculator_behavioral
(
    input             clock,
    input             reset,
    input             enter,
    input             add,
    input             multiply,
    input      [ 7:0] data,
    output reg [15:0] result,
    output reg        overflow,
    output reg [ 3:0] error
);

    reg [`stack_pointer_size - 1:0] sp;
    reg [15:0] stack [0 : `stack_size - 1];
    reg        empty;

    reg [16:0] result_17;
    reg [31:0] result_32;

    integer i;

    //  This software-like style is not a good RTL style because:
    //
    //  1. It mixes blocking and non-blocking assignments
    //
    //  2. It is difficult to figure out whether a reg
    //     is going to become a flip-flop or a wire
    //
    //  3. It makes timing optimization difficult
    //
    //  However this style of coding is easier to read for a software
    //  or a verification person

    always @(posedge clock or posedge reset)
    begin
        if (reset)
        begin
            sp        =  0;
            empty     =  1;

            result    <= 0;
            overflow  <= 0;
            error     <= 0;
        end
        else
        begin
            if (enter)
            begin
                if (sp == `stack_size - 1)
                begin
                    error <= 1;
                end
                else
                begin
                    if (! empty)                       // Вокруг плохой стиль для RTL - смешивается blocking и non-blocking,
                        sp = sp + 1;                // неочевидно, какой регистр превратится в D-триггер, 
                                                          // а какой нет; трудно оптимизировать тайминг.
                    empty = 0;

                    for (i = `stack_size - 1; i >= 1; i = i - 1)
                        stack [i] = stack [i - 1];

                    stack [0] = data;
                end
            end
            else if (add)
            begin
                if (sp == 0)
                begin
                    error <= 2;
                end
                else
                begin
                    sp = sp - 1;

                    result_17 = stack [0] + stack [1];
                    stack [0] = result_17 [15:0];
                    overflow <= result_17 [16];

                    for (i = 1; i <= `stack_size - 2; i = i + 1)
                        stack [i] = stack [i + 1];
                end
            end
            else if (multiply)
            begin
                if (sp == 0)
                begin
                    error <= 3;
                end
                else
                begin
                    sp = sp - 1;

                    result_32 = stack [0] * stack [1];
                    stack [0] = result_32 [15:0];
                    overflow <= | result_32 [31:16];

                    for (i = 1; i <= `stack_size - 2; i = i + 1)
                        stack [i] = stack [i + 1];
                end
            end

            result <= empty ? 0 : stack [0];
        end
    end

endmodule

//-------------------------------------------------------------------------//
//
//  defines.vh
//
//-------------------------------------------------------------------------//

`ifdef word_width
`else
`define word_width 16
`endif

`ifdef stack_size
`else
`define stack_size 4
`endif

`ifdef stack_pointer_size
`else
`define stack_pointer_size 2
`endif

//-------------------------------------------------------------------------//
//
//  alu.v
//
//-------------------------------------------------------------------------//

module alu
(
    input  [15:0] a,
    input  [15:0] b,
    input         multiply,
    output [15:0] result,
    output        overflow
);

    wire [16:0] result_add = a + b;
    wire [31:0] result_mul = a * b;

    assign result   = multiply ?   result_mul [15: 0] : result_add [15:0];
    assign overflow = multiply ? | result_mul [31:16] : result_add [16];

endmodule

//-------------------------------------------------------------------------//
//
//  stack.v
//
//-------------------------------------------------------------------------//

`include "defines.vh"

module stack
(
    input  clock,
    input  reset,
    input  push,
    input  pop,

    input  [`word_width - 1:0] write_data,
    output [`word_width - 1:0] read_data
);

    reg [`word_width - 1:0] stack [0:`stack_size - 1];

    assign read_data = stack [0];

    integer i;

    always @(posedge clock)
    begin
        if (reset)
        begin
            for (i = 0; i < `stack_size; i = i + 1)
                stack [i] <= 0;
        end
        else if (push)
        begin
            for (i = 0; i < `stack_size - 1; i = i + 1)
                stack [i + 1] <= stack [i];

            stack [0] <= write_data;
        end
        else if (pop)
        begin
            for (i = 0; i < `stack_size - 1; i = i + 1)
                stack [i] <= stack [i + 1];

            stack [`stack_size - 1] <= 0;
        end
    end

endmodule



//-------------------------------------------------------------------------//
//
//  chip.ucf
//
//-------------------------------------------------------------------------//

NET "mclk" LOC = "B8"; # Bank = 0, Signal name = MCLK
NET "mclk" CLOCK_DEDICATED_ROUTE = FALSE;

NET "mclk" PERIOD = 20 ns HIGH 50%;

#TIMESPEC TS01 = FROM : FFS : TO : FFS : 20 ns;
#TIMESPEC TS02 = FROM : RAMS : TO : FFS : 20 ns;
#TIMESPEC TS03 = FROM : FFS : TO : RAMS : 20 ns;
#TIMESPEC TS04 = FROM : RAMS : TO : RAMS : 20 ns;
#TIMESPEC TS05 = FROM : FFS : TO : PADS : 20 ns;
#TIMESPEC TS06 = FROM : PADS : TO : FFS : 20 ns;
#TIMESPEC TS07 = FROM : PADS : TO : RAMS : 20 ns;


# Pin assignment for DispCtl
# Connected to Basys2 onBoard 7seg display
NET "seg<0>" LOC = "L14"; # Bank = 1, Signal name = CA
NET "seg<1>" LOC = "H12"; # Bank = 1, Signal name = CB
NET "seg<2>" LOC = "N14"; # Bank = 1, Signal name = CC
NET "seg<3>" LOC = "N11"; # Bank = 2, Signal name = CD
NET "seg<4>" LOC = "P12"; # Bank = 2, Signal name = CE
NET "seg<5>" LOC = "L13"; # Bank = 1, Signal name = CF
NET "seg<6>" LOC = "M12"; # Bank = 1, Signal name = CG
NET "dp" LOC = "N13"; # Bank = 1, Signal name = DP

NET "an<3>" LOC = "K14"; # Bank = 1, Signal name = AN3
NET "an<2>" LOC = "M13"; # Bank = 1, Signal name = AN2
NET "an<1>" LOC = "J12"; # Bank = 1, Signal name = AN1
NET "an<0>" LOC = "F12"; # Bank = 1, Signal name = AN0

# Pin assignment for LEDs
NET "Led<7>" LOC = "G1" ; # Bank = 3, Signal name = LD7
NET "Led<6>" LOC = "P4" ; # Bank = 2, Signal name = LD6
NET "Led<5>" LOC = "N4" ;  # Bank = 2, Signal name = LD5
NET "Led<4>" LOC = "N5" ;  # Bank = 2, Signal name = LD4
NET "Led<3>" LOC = "P6" ; # Bank = 2, Signal name = LD3
NET "Led<2>" LOC = "P7" ; # Bank = 3, Signal name = LD2
NET "Led<1>" LOC = "M11" ; # Bank = 2, Signal name = LD1
NET "Led<0>" LOC = "M5" ;  # Bank = 2, Signal name = LD0

# Pin assignment for SWs
NET "sw<7>" LOC = "N3";  # Bank = 2, Signal name = SW7
NET "sw<6>" LOC = "E2";  # Bank = 3, Signal name = SW6
NET "sw<5>" LOC = "F3";  # Bank = 3, Signal name = SW5
NET "sw<4>" LOC = "G3";  # Bank = 3, Signal name = SW4
NET "sw<3>" LOC = "B4";  # Bank = 3, Signal name = SW3
NET "sw<2>" LOC = "K3";  # Bank = 3, Signal name = SW2
NET "sw<1>" LOC = "L3";  # Bank = 3, Signal name = SW1
NET "sw<0>" LOC = "P11";  # Bank = 2, Signal name = SW0

NET "btn<3>" LOC = "A7";  # Bank = 1, Signal name = BTN3
NET "btn<2>" LOC = "M4";  # Bank = 0, Signal name = BTN2
NET "btn<1>" LOC = "C11"; # Bank = 2, Signal name = BTN1
NET "btn<0>" LOC = "G12"; # Bank = 0, Signal name = BTN0

//-------------------------------------------------------------------------//
//
//  chip.v
//
//-------------------------------------------------------------------------//

module chip
(
    input        mclk,
    output [6:0] seg,
    output       dp,
    output [3:0] an,
    output [7:0] Led,
    input  [7:0] sw,
    input  [3:0] btn
);

    system system
    (
        .clock          ( mclk ),
        .switches       ( sw   ),
        .buttons        ( btn  ),
        .leds           ( Led  ),
        .seven_segments ( seg  ),
        .dot            ( dp   ),
        .anodes         ( an   )
    );

endmodule

//-------------------------------------------------------------------------//
//
//  system.v
//
//-------------------------------------------------------------------------//

module system
(
    input            clock,
    input      [7:0] switches,
    input      [3:0] buttons,
    output reg [7:0] leds,
    output     [6:0] seven_segments,
    output           dot,
    output     [3:0] anodes
);

    wire reset = buttons [3];
    wire clock_for_debouncing;
    wire clock_for_display;

    clock_divider clock_divider
    (
        clock,
        reset,
        clock_for_debouncing,
        clock_for_display
    );

    wire enter;
    wire add;
    wire multiply;

    debouncer debouncer2
        ( clock, clock_for_debouncing, reset, buttons [2], enter    );

    debouncer debouncer1
        ( clock, clock_for_debouncing, reset, buttons [1], add      );

    debouncer debouncer0
        ( clock, clock_for_debouncing, reset, buttons [0], multiply );

    wire [ 7:0] data;
    wire [15:0] result;
    wire        overflow;
    wire [ 3:0] error;

    assign data = switches;

    display display
    (
        clock_for_display,
        reset,
        result,
        overflow,
        error,
        seven_segments,
        dot,
        anodes
    );

    calculator calculator
    (
        clock,
        reset,
        enter,
        add,
        multiply,
        data,
        result,
        overflow,
        error
    );

    always @(posedge clock_for_display)
        leds <= reset ? 0 : switches;

endmodule

//-------------------------------------------------------------------------//
//
//  clock_divider.v
//
//-------------------------------------------------------------------------//

module clock_divider
(
    input  clock,
    input  reset,
    output clock_for_debouncing,
    output clock_for_display
);

    reg [19:0] counter;

    always @(posedge clock)
    begin
        if (reset)
            counter <= 0;
        else
            counter <= counter + 1;
    end

    assign clock_for_debouncing = counter [19];
    assign clock_for_display    = counter [15];

endmodule

//-------------------------------------------------------------------------//
//
//  debouncer.v
//
//-------------------------------------------------------------------------//

module debouncer
(
    input      clock,
    input      clock_for_debouncing,
    input      reset,
    input      button,
    output reg push
);

    reg [2:0] samples;

    always @(posedge clock_for_debouncing)
    begin
        if (reset)
            samples <= 0;
        else
            samples <= { samples [1:0], button };
    end

    wire current = & samples;
    reg  previous;

    always @(posedge clock)
    begin
        if (reset)
        begin
            previous <= 0;
            push     <= 0;
        end
        else
        begin
            previous <= current;
            push     <= { previous, current } == 2'b01;
        end
    end

endmodule

//-------------------------------------------------------------------------//
//
//  display.v
//
//-------------------------------------------------------------------------//

module display
(
    input             clock,
    input             reset,
    input      [15:0] number,
    input             overflow,
    input      [ 3:0] error,

    output reg [ 6:0] seven_segments,
    output reg        dot,
    output reg [ 3:0] anodes
);

    parameter [6:0] seg_E = 'b0000110;
    parameter [6:0] seg_r = 'b0101111;

    function [6:0] bcd_to_seg (input [3:0] bcd);

        case (bcd)
        'h0: bcd_to_seg = 'b1000000;  // a b c d e f g
        'h1: bcd_to_seg = 'b1111001;
        'h2: bcd_to_seg = 'b0100100;  //   --a--
        'h3: bcd_to_seg = 'b0110000;  //  |     |
        'h4: bcd_to_seg = 'b0011001;  //  f     b
        'h5: bcd_to_seg = 'b0010010;  //  |     |
        'h6: bcd_to_seg = 'b0000010;  //   --g--
        'h7: bcd_to_seg = 'b1111000;  //  |     |
        'h8: bcd_to_seg = 'b0000000;  //  e     c
        'h9: bcd_to_seg = 'b0011000;  //  |     |
        'ha: bcd_to_seg = 'b0001000;  //   --d-- 
        'hb: bcd_to_seg = 'b0000011;
        'hc: bcd_to_seg = 'b1000110;
        'hd: bcd_to_seg = 'b0100001;
        'he: bcd_to_seg = 'b0000110;
        'hf: bcd_to_seg = 'b0001110;
        endcase

    endfunction

    reg [1:0] i;

    always @(posedge clock)
    begin
        if (reset)
        begin
            i <= 0;

            seven_segments <=   bcd_to_seg (0);
            dot            <= ~ 0;
            anodes         <= ~ 'b1111;
        end
        else
        begin
            if (error != 0)
            begin
                case (i)
                0    : seven_segments <= bcd_to_seg (error);
                1, 2 : seven_segments <= seg_r;
                3    : seven_segments <= seg_E;
                endcase

                dot            <= ~ 0;
                anodes         <= ~ (1 << i);
            end
            else
            begin
                seven_segments <=   bcd_to_seg (number [i * 4 +: 4]);
                dot            <= ~ (i == 0 ? overflow : 0);
                anodes         <= ~ (1 << i);
            end

            i <= i + 1;
        end
    end

endmodule

//-------------------------------------------------------------------------//
//
//  testbench.v
//
//-------------------------------------------------------------------------//

module testbench;

    reg         clock;
    reg         reset;
    reg         enter;
    reg         add;
    reg         multiply;
    reg  [ 7:0] data;
    wire [15:0] result;
    wire        overflow;
    wire [ 3:0] error;

    calculator calculator
    (
        clock,
        reset,
        enter,
        add,
        multiply,
        data,
        result,
        overflow,
        error
    );

    initial
    begin
        clock = 0;

        forever
            # 5 clock = ! clock;
    end

    //----------------------------------------------------------------

    task dump;
    begin

        $write   ("data=%h enter=%h add=%h multiply=%h",
                   data,   enter,   add,   multiply);

        $display (" result=%h overflow=%h error=%h",
                    result,   overflow,   error);

    end
    endtask

    task t_reset;
    begin

        reset     <= 1; repeat (10) @(posedge clock);

        enter     <= 0;
        add       <= 0;
        multiply  <= 0;
        data      <= 0;

        reset     <= 0; repeat (10) @(posedge clock);

        $write ("After reset    "); dump;

    end
    endtask

    task t_enter (input [7:0] value);
    begin

        data      <= value;
        enter     <= 1;             @(posedge clock);
        enter     <= 0; repeat (10) @(posedge clock);

        $write ("After enter %x ", value); dump;

    end
    endtask

    task t_add;
    begin

        add       <= 1;             @(posedge clock);
        add       <= 0; repeat (10) @(posedge clock);

        $write ("After add      "); dump;

    end
    endtask

    task t_multiply;
    begin

        multiply  <= 1;             @(posedge clock);
        multiply  <= 0; repeat (10) @(posedge clock);

        $write ("After multiply "); dump;

    end
    endtask

    //----------------------------------------------------------------

    initial
    begin
        $display ("********  2 3 * 4 5 * + ********");

        t_reset;

        t_enter (2);
        t_enter (3);
        t_multiply;
        t_enter (4);
        t_enter (5);
        t_multiply;
        t_add;

        $display ("********  ff ff ff * * overflow ********");

        t_reset;

        t_enter ('hff);
        t_enter ('hff);
        t_enter ('hff);
        t_multiply;
        t_multiply;

        $display ("********  ff 1 + ff * ff + 1 + overflow ********");

        t_reset;

        t_enter ('hff);
        t_enter ('h01);
        t_add;
        t_enter ('hff);
        t_multiply;
        t_enter ('hff);
        t_add;
        t_enter ('h01);
        t_add;

        $display ("********  1 2 3 4 5 * * * * * ********");

        t_reset;

        t_enter ('h01);
        t_enter ('h02);
        t_enter ('h03);
        t_enter ('h04);
        t_enter ('h05);
        repeat (5) t_multiply;

        $finish;
    end

    initial $dumpvars;

endmodule



Poll #1835851 Примерчик на верилоге для начинающих - стековый калькулятор

Какие еще примерчики могли бы быть полезными для вводного или последующих курсов?

Простой кэш прямого отображения
3(4.2%)
n-канальный ассоциативный кэш
3(4.2%)
Процессорик с одним аккумулятором, оперативной памятью, несколькими командами арифметики и ветвления, команда в один цикл
10(14.1%)
Процессорик с регистровым файлом, без оперативной памяти, несколькими команд, команда в один цикл
7(9.9%)
Процессорик с регистровым файлом, без оперативной памяти, с небольшим последовательным конвейером и stalls
4(5.6%)
То же, но еще и с forwarding
4(5.6%)
То же, но еще и c branch prediction
5(7.0%)
То же, но еще и c какой-нибудь демонстрацией суперскалярности
5(7.0%)
Векторный сопроцессор
5(7.0%)
Алгоритм шифрования
4(5.6%)
Дать студентам в качестве курсовых работ сделать на FPGA аналог первых процессоров - ENIAC, МЭСМ
4(5.6%)
Дать студентам в качестве курсовых работ сделать на FPGA аналог старых процессоров - PDP-8, Минск-1, Урал-1
6(8.5%)
DSP фильтр или подобные штучки
4(5.6%)
Робот на колесиках с дальномеркой в качестве глаз
6(8.5%)
Другое (пояснить в комментариях)
1(1.4%)

Как вы думаете, для такого курса лучше стандартизироваться на Xilinx или Altera?

Xilinx
3(16.7%)
Altera
0(0.0%)
Каждый студент должен попробовать и то, и другое
8(44.4%)
Пол группы на Xilinx, пол группы на Altera, а потом устроить между группами соревнование
6(33.3%)
Другое (пояснить в комментариях)
1(5.6%)

Другие мысли

А зачем это? Фурсенко сказал, что нужно взрастить квалифицированного потребителя
6(42.9%)
Бросьте! То же самое могут прочитать и в Сколково за 600 миллионов долларов мудрецы из MIT. И закон Ома они лучше объяснят.
0(0.0%)
Экслер уже объяснил, насколько смехотворны рычажки. Истинное обучение технологии - это как настроить Айфон.
1(7.1%)
В Сан-Франциско намедни побывала Чирикова. Как Панчул упустил возможность разыграть с ней "Высурковскаяпропаганда" на улице?
4(28.6%)
Из-за бугра плюете?
3(21.4%)


UPD: Сергей Вакуленко подошел и высказал мнение, что в такие серьезные посты нельзя помещать женские груди. Я сказал, что грудями ЖЖ не испортишь. На том и разошлись. Думаю.

ljpromo, приди!
Tags: important, nntu
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 78 comments
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →