О портировании проекта MIPSfpga



    Перенос программного обеспечения с одной компьютерной архитектуры на другую в принципе, с некоторыми оговорками, дело относительно простое. Здесь на помощь приходят такие общеизвестные инструменты, как autoconf / automake/ libtool / gnulib. Собрать программу из исходников на каком нибудь Raspberry/ARM бывает так же просто, как и на ПК с Ubuntu/x86-64.

    А вот как заставить проект ПЛИС разработанный для одной платы работать на другой плате? Там и сама ПЛИС может быть другой и на плате совершенно другие компоненты могут стоять. Простой перекомпиляцией проекта не обойтись.

    Расскажу о своем опыте портирования проекта MIPSfpga для платы Марсоход3 с ПЛИС MAX10 Intel. Статьи о проекте MIPSfpga неоднократно появлялись на хабре. Они были так интересны, что мне захотелось и самому попробовать этот проект в имеющейся у меня плате. В своей работе я опирался на хабровские статьи


    И многие другие…

    Итак, что нужно сделать, чтобы портировать проект ПЛИС на другую плату?

    1) Нужно переназначить тип используемой ПЛИС в проекте


    Повезет, если исходный проект ориентирован на точно такую же микросхему ПЛИС, как и на вашей плате. Проект MIPSfpga уже был портирован на платы разных производителей, в том числе, там есть платы и с FPGA Xilinx и платы с FPGA Intel/Altera. Тем не менее, скажем так, мне «не повезло». Да, есть проект для платы DE10-lite и там используется ПЛИС MAX10, как и на моей плате. Но это совершенно другая MAX10 — на DE10-lite стоит 10M50DAF484C7G, а на плате Марсоход3 стоит ПЛИС MAX1050SAE144C8. Обе микросхемы имеют 50 тысяч логических элементов, но у первой гораздо больше входных/выходных сигналов. Понятно, что вместе с переназначением типа микросхемы ПЛИС «слетают» все назначения сигналов на конкретные выводы микросхемы.



    Назначение типа используемой микросхемы в среде САПР Intel Quartus производится через меню Assignments => Device в диалоговом окне Device.

    Здесь же есть кнопка Device And Pin Options — зайдите туда в следующее диалоговое окно и я очень рекомендую сразу указать, что неиспользуемые в проекте пины должны быть As input tri-state.



    Если плата не очень знакома, ее схему, например, мы досконально пока не изучили, лучше неиспользуеые выводы ПЛИС отключить от цепей платы.

    2) Сделать новые назначения входам и выходам


    Поскольку тип микросхемы был переназначен, то теперь нужно указать на какие входы/выходы идут те или иные сигналы проекта ПЛИС. В каждом проекте ПЛИС есть модуль самого верхнего уровня. Сигналы этого модуля соединены с выводами микросхемы ПЛИС, с теми, куда мы укажем в настройках проекта.

    Вот, например, в моем проекте:

    module m3
    (
        input           MAX10_CLK_100,
        input   [ 1:0]  KEY,
        output  [ 7:0]  LEDR,
    	 input wire  FTDI_RX,
    	 output wire FTDI_TX,
    	 inout wire [7:0]FTD,
    
        `ifdef MFP_USE_SDRAM_MEMORY
            output  [11:0]  DRAM_ADDR,
            output  [ 1:0]  DRAM_BA,
            output          DRAM_CAS_N,
            //output          DRAM_CKE,
            output          DRAM_CLK,
            //output          DRAM_CS_N,
            inout   [15:0]  DRAM_DQ,
            output          DRAM_LDQM,
            output          DRAM_RAS_N,
            output          DRAM_UDQM,
            output          DRAM_WE_N,
        `endif
        
        `ifdef UNUSED
    	     input           ADC_CLK_10,
    		  input           MAX10_CLK1_50,
    		  input           MAX10_CLK2_50,
    
    		  input   [ 9:0]  SW,
    		  output  [ 7:0]  HEX0,
    		  output  [ 7:0]  HEX1,
    		  output  [ 7:0]  HEX2,
    		  output  [ 7:0]  HEX3,
    		  output  [ 7:0]  HEX4,
    		  output  [ 7:0]  HEX5,
            output  [ 3:0]  VGA_B,
            output  [ 3:0]  VGA_G,
            output          VGA_HS,
            output  [ 3:0]  VGA_R,
            output          VGA_VS,
            output          GSENSOR_CS_N,
            input   [ 2:1]  GSENSOR_INT,
            output          GSENSOR_SCLK,
            inout           GSENSOR_SDI,
            inout           GSENSOR_SDO,
            inout   [15:0]  ARDUINO_IO,
            inout           ARDUINO_RESET_N,
    		  inout   [35:0]  GPIO,
        `endif
    
    		  inout   [15:0]  GPIO,
    		  
    		  //HDMI output
    		  output wire [7:0]TMDS
    );

    На плате Марсоход3 нет ни переключателей SW, ни семисегментных индикаторов HEX0..HEX5, ни VGA разъема. Эти сигналы я не стал прямо удалять из проекта, но удалил их условной компиляцией с помощью конструкции `if UNUSED… `endif. На плате Марсоход3 есть светодиоды, кнопочки, сигналы с FTDI и даже HDMI сигналы — вот они присутствуют в моем проекте.



    В среде Quartus через меню Assigments => Assignment Editor нужно задать соответствие сигнала номеру контакта микросхемы. Конечно, это нужно делать согласно схемы платы электрической принципиальной. Кроме указания номера вывода микросхемы возможно понадобится сделать другие назначения вроде i/O Standard или Pull-Up Resistor, если необходимо.

    3) Внимание на тактовую частоту


    Вероятно, что исходный проект сделан для платы у которой номинал кварцевого генератора не такой, как на нашей плате. Так и оказалось в моем случае. Плата DE10-lite имеет генератор 50МГц, а моя плата — 100МГц. Что нужно сделать — пересоздать экземпляр модуля PLL для данного проекта. В меню квартуса выбираем Tools => IP Catalog, там среди Installed IPs => Libraries находим basic Functions => Clocks; PLLs and Reset => PLLs => ALTPLL и запускаем Wizard.



    Нужно указать правильную исходную частоту и в PLL задать нужные выходные частоту. Тут придется учитывать много факторов. Я решил добавить в проект вывод на HDMI дисплей, которого не было в исходном проекте, а значит мне понадобились дополнительные частоты требующиеся непосредственно для формирования видеосигналов TMDS (74МГц и 370МГц).

    Созданную вариацию компонента PLL потом нужно вставить в проект.

    4) Урезать или расширить функционал?


    В случае портирования проектов ПЛИС на другие платы часто сталкиваешься с тем, что повторить проект один-в-один не удастся. Самая простая причина — например, исходный проект сделан для платы у которой есть 16 светодиодов и/или семисегментные индикаторы, а на нашей плате например такого вообще нет, или светодионы есть, но их меньше, не шестнадцать, а только восемь. Или на плате стоит другой объем ОЗУ или флэш… Тут приходится что-то придумывать, как-то обходить ограничения.

    Я решил, что поскольку проект MIPSfpga обучающий и отображать информацию действительно как-то нужно, а иначе теряется «визуальность проекта», значит я буду отображать информацию на мониторе.

    Для этой цели я написал на Verilog модуль виртуальных светодиодов и семисегментных индикаторов.

    Приведу текст модуля здесь целиком:

    Модуль виртуальных светодиодов и индикаторов
    //marsohod3 board has only 8 yellow LEDs
    //but sample MIPS needs red/green LEDs and 7-segment indicators
    //so try display LEDs and 7-segment info on HDMI output of Marsohod3 board
    
    module display 
    		(
    		input wire reset,
    		input wire clk_video,	//74MHz
    		input wire clk_hdmi,		//370MHz
    		input wire [NUM_RED_LEDS-1:0]red_leds,
    		input wire [NUM_GREEN_LEDS-1:0]green_leds,
    		input wire [NUM_SEGMENTS*4-1:0]segments,
    		//HDMI output
    		output wire [7:0]TMDS
    	   );
    	   
    parameter NUM_RED_LEDS = 16;
    parameter NUM_GREEN_LEDS = 16;
    parameter NUM_SEGMENTS = 6;
    
    wire w_hsync;
    wire w_vsync;
    wire w_active;
    wire [11:0]w_pixel_count;
    wire [11:0]w_line_count;
    
    wire w_video_clk5; assign w_video_clk5 = clk_hdmi;
    wire w_video_clk; assign w_video_clk = clk_video;
    
    hvsync u_hvsync(
    	.reset( reset ),
    	.pixel_clock( w_video_clk ),
    
    	.hsync(w_hsync),
    	.vsync(w_vsync),
    	.active(w_active),
    
    	.pixel_count(w_pixel_count),
    	.line_count(w_line_count),
    	.dbg( )
    	);
    
    reg d_active;
    reg r_hsync;
    reg r_vsync;
    reg r_vsync_;
    reg [NUM_RED_LEDS-1:0]red_leds_fixed;
    reg [NUM_GREEN_LEDS-1:0]green_leds_fixed;
    reg [NUM_SEGMENTS*4-1:0]segments_fixed;
    
    always @(posedge w_video_clk)
    begin
    	r_hsync  <= w_hsync;
    	r_vsync  <= w_vsync;
    	r_vsync_ <= r_vsync;
    	d_active <= w_active;
    	if( r_vsync_==1'b0 && r_vsync==1'b1 )
    	begin
    		red_leds_fixed <= red_leds;
    		green_leds_fixed <= green_leds;
    		segments_fixed <= segments;
    	end
    end
    
    reg [9:0]red_word;
    reg [9:0]green_word;
    reg [9:0]blue_word;
    
    wire led_visible; assign led_visible = w_pixel_count<512 && w_pixel_count[4]==1'b1;
    wire [3:0]led_idx; assign led_idx = NUM_RED_LEDS-1-w_pixel_count[8:5];
    wire current_green_led = (green_leds_fixed >> led_idx)&1;
    wire current_red_led = (red_leds_fixed >> led_idx)&1;
    
    wire h_seg_line5; assign h_seg_line5 = w_pixel_count<(64*1-8) && w_pixel_count>(64*0+32);
    wire h_seg_line4; assign h_seg_line4 = w_pixel_count<(64*2-8) && w_pixel_count>(64*1+32);
    wire h_seg_line3; assign h_seg_line3 = w_pixel_count<(64*3-8) && w_pixel_count>(64*2+32);
    wire h_seg_line2; assign h_seg_line2 = w_pixel_count<(64*4-8) && w_pixel_count>(64*3+32);
    wire h_seg_line1; assign h_seg_line1 = w_pixel_count<(64*5-8) && w_pixel_count>(64*4+32);
    wire h_seg_line0; assign h_seg_line0 = w_pixel_count<(64*6-8) && w_pixel_count>(64*5+32);
    
    wire vl_seg_line5; assign vl_seg_line5 = w_pixel_count<(64*1-32) && w_pixel_count>(64*0+24);
    wire vl_seg_line4; assign vl_seg_line4 = w_pixel_count<(64*2-32) && w_pixel_count>(64*1+24);
    wire vl_seg_line3; assign vl_seg_line3 = w_pixel_count<(64*3-32) && w_pixel_count>(64*2+24);
    wire vl_seg_line2; assign vl_seg_line2 = w_pixel_count<(64*4-32) && w_pixel_count>(64*3+24);
    wire vl_seg_line1; assign vl_seg_line1 = w_pixel_count<(64*5-32) && w_pixel_count>(64*4+24);
    wire vl_seg_line0; assign vl_seg_line0 = w_pixel_count<(64*6-32) && w_pixel_count>(64*5+24);
    
    wire vr_seg_line5; assign vr_seg_line5 = w_pixel_count<(64*1) && w_pixel_count>(64*0+56);
    wire vr_seg_line4; assign vr_seg_line4 = w_pixel_count<(64*2) && w_pixel_count>(64*1+56);
    wire vr_seg_line3; assign vr_seg_line3 = w_pixel_count<(64*3) && w_pixel_count>(64*2+56);
    wire vr_seg_line2; assign vr_seg_line2 = w_pixel_count<(64*4) && w_pixel_count>(64*3+56);
    wire vr_seg_line1; assign vr_seg_line1 = w_pixel_count<(64*5) && w_pixel_count>(64*4+56);
    wire vr_seg_line0; assign vr_seg_line0 = w_pixel_count<(64*6) && w_pixel_count>(64*5+56);
    
    function  [7:0]seg7;
    input [3:0]a;
    begin
    	case(a)
    	0: seg7 = 63;
    	1: seg7 = 6;
    	2: seg7 = 91;
    	3: seg7 = 79;
    	4: seg7 = 102;
    	5: seg7 = 109;
    	6: seg7 = 125;
    	7: seg7 = 7;
    	8: seg7 = 127;
    	9: seg7 = 111;
    	10: seg7 = 119;
    	11: seg7 = 124;
    	12: seg7 = 57;
    	13: seg7 = 94;
    	14: seg7 = 121;
    	15: seg7 = 113;
    	endcase
    end
    endfunction
    
    reg [6:0]seg7_0;
    reg [6:0]seg7_1;
    reg [6:0]seg7_2;
    reg [6:0]seg7_3;
    reg [6:0]seg7_4;
    reg [6:0]seg7_5;
    
    always @(posedge clk_video)
    begin
    	seg7_0 <= seg7( segments_fixed[ 3: 0] );
    	seg7_1 <= seg7( segments_fixed[ 7: 4] );
    	seg7_2 <= seg7( segments_fixed[11: 8] );
    	seg7_3 <= seg7( segments_fixed[15:12] );
    	seg7_4 <= seg7( segments_fixed[19:16] );
    	seg7_5 <= seg7( segments_fixed[23:20] );
    end
    
    reg [2:0]color;
    
    always @*
    begin
    	if( w_line_count>64 && w_line_count<80 ) begin
    		//green led line
    		if(led_visible)
    			color = current_green_led ? 1 : 2;
    		else color=0;
    	end
    	else
    	if( w_line_count>96 && w_line_count<112 ) begin
    		//red led line
    		if(led_visible)
    			color = current_red_led ? 3 : 4;
    		else color=0;
    	end
    	else
    	if( w_line_count>118+32 && w_line_count<126+32 ) begin
    		// 7seg top line
    		if(h_seg_line0)
    			color = seg7_0[0] ? 5 : 6;
    		else
    		if(h_seg_line1)
    			color = seg7_1[0] ? 5 : 6;
    		else 
    		if(h_seg_line2)
    			color = seg7_2[0] ? 5 : 6;
    		else 
    		if(h_seg_line3)
    			color = seg7_3[0] ? 5 : 6;
    		else 
    		if(h_seg_line4)
    			color = seg7_4[0] ? 5 : 6;
    		else 
    		if(h_seg_line5)
    			color = seg7_5[0] ? 5 : 6;
    		else 
    			color=0;
    	end
    	else
    	if( w_line_count>126+32 && w_line_count<148+32 ) begin
    		if(vr_seg_line0)
    			color = seg7_0[1] ? 5 : 6;
    		else
    		if(vr_seg_line1)
    			color = seg7_1[1] ? 5 : 6;
    		else 
    		if(vr_seg_line2)
    			color = seg7_2[1] ? 5 : 6;
    		else 
    		if(vr_seg_line3)
    			color = seg7_3[1] ? 5 : 6;
    		else 
    		if(vr_seg_line4)
    			color = seg7_4[1] ? 5 : 6;
    		else 
    		if(vr_seg_line5)
    			color = seg7_5[1] ? 5 : 6;
    		else 
    		if(vl_seg_line0)
    			color = seg7_0[5] ? 5 : 6;
    		else
    		if(vl_seg_line1)
    			color = seg7_1[5] ? 5 : 6;
    		else 
    		if(vl_seg_line2)
    			color = seg7_2[5] ? 5 : 6;
    		else 
    		if(vl_seg_line3)
    			color = seg7_3[5] ? 5 : 6;
    		else 
    		if(vl_seg_line4)
    			color = seg7_4[5] ? 5 : 6;
    		else 
    		if(vl_seg_line5)
    			color = seg7_5[5] ? 5 : 6;
    		else
    			color=0;
    	end
    	else
    	if( w_line_count>148+32 && w_line_count<156+32 ) begin
    		// 7seg middle line
    		if(h_seg_line0)
    			color = seg7_0[6] ? 5 : 6;
    		else
    		if(h_seg_line1)
    			color = seg7_1[6] ? 5 : 6;
    		else 
    		if(h_seg_line2)
    			color = seg7_2[6] ? 5 : 6;
    		else 
    		if(h_seg_line3)
    			color = seg7_3[6] ? 5 : 6;
    		else 
    		if(h_seg_line4)
    			color = seg7_4[6] ? 5 : 6;
    		else 
    		if(h_seg_line5)
    			color = seg7_5[6] ? 5 : 6;
    		else 
    			color=0;
    	end
    	else
    	if( w_line_count>156+32 && w_line_count<180+32 ) begin
    		if(vr_seg_line0)
    			color = seg7_0[2] ? 5 : 6;
    		else
    		if(vr_seg_line1)
    			color = seg7_1[2] ? 5 : 6;
    		else 
    		if(vr_seg_line2)
    			color = seg7_2[2] ? 5 : 6;
    		else 
    		if(vr_seg_line3)
    			color = seg7_3[2] ? 5 : 6;
    		else 
    		if(vr_seg_line4)
    			color = seg7_4[2] ? 5 : 6;
    		else 
    		if(vr_seg_line5)
    			color = seg7_5[2] ? 5 : 6;
    		else 
    		if(vl_seg_line0)
    			color = seg7_0[4] ? 5 : 6;
    		else
    		if(vl_seg_line1)
    			color = seg7_1[4] ? 5 : 6;
    		else 
    		if(vl_seg_line2)
    			color = seg7_2[4] ? 5 : 6;
    		else 
    		if(vl_seg_line3)
    			color = seg7_3[4] ? 5 : 6;
    		else 
    		if(vl_seg_line4)
    			color = seg7_4[4] ? 5 : 6;
    		else 
    		if(vl_seg_line5)
    			color = seg7_5[4] ? 5 : 6;
    		else
    			color=0;
    	end
    	else
    	if( w_line_count>180+32 && w_line_count<188+32 ) begin
    		// 7seg bottom line
    		if(h_seg_line0)
    			color = seg7_0[3] ? 5 : 6;
    		else
    		if(h_seg_line1)
    			color = seg7_1[3] ? 5 : 6;
    		else 
    		if(h_seg_line2)
    			color = seg7_2[3] ? 5 : 6;
    		else 
    		if(h_seg_line3)
    			color = seg7_3[3] ? 5 : 6;
    		else 
    		if(h_seg_line4)
    			color = seg7_4[3] ? 5 : 6;
    		else 
    		if(h_seg_line5)
    			color = seg7_5[3] ? 5 : 6;
    		else 
    			color=0;
    	end
    	else
    		color=0;
    end
    
    reg [2:0]color_fixed;
    always @(posedge clk_video)
    	color_fixed<=color;
    
    always @*
    begin
    	case(color_fixed)
    	0: begin //gray
    			red_word   = 10'b0000011111;
    			green_word = 10'b0000011111;
    			blue_word  = 10'b0000111111;
    		end
    	1: begin //bright green
    			red_word   = 10'b0000011111;
    			green_word = 10'b1111111111;
    			blue_word  = 10'b0000011111;
    		end
    	2: begin //dark green
    			red_word   = 10'b0000011111;
    			green_word = 10'b0000111111;
    			blue_word  = 10'b0000011111;
    		end
    	3: begin //bright red
    			red_word   = 10'b1111111111;
    			green_word = 10'b0000011111;
    			blue_word  = 10'b0000011111;
    		end
    	4: begin //dark red
    			red_word   = 10'b0000111111;
    			green_word = 10'b0000011111;
    			blue_word  = 10'b0000011111;
    		end
    	5: begin //bright yellow
    			red_word   = 10'b1111111111;
    			green_word = 10'b1111111111;
    			blue_word  = 10'b0000011111;
    		end
    	6: begin //dark yellow
    			red_word   = 10'b0000111111;
    			green_word = 10'b0000111111;
    			blue_word  = 10'b0000011111;
    		end
    	7: begin //gray
    			red_word   = 10'b0000011111;
    			green_word = 10'b0000011111;
    			blue_word  = 10'b0000111111;
    		end		
    	endcase
    end
    
    wire w_tmds_bh;
    wire w_tmds_bl;
    wire w_tmds_gh;
    wire w_tmds_gl;
    wire w_tmds_rh;
    wire w_tmds_rl;
    
    hdmi u_hdmi(
    	.pixclk( w_video_clk ),
    	.clk_TMDS2( w_video_clk5 ),
    	.hsync( r_hsync ),
    	.vsync( r_vsync ),
    	.active( d_active ),
    	.red( red_word ),
    	.green( green_word ),
    	.blue( blue_word ),
    	.TMDS_bh( w_tmds_bh ),
    	.TMDS_bl( w_tmds_bl ),
    	.TMDS_gh( w_tmds_gh ),
    	.TMDS_gl( w_tmds_gl ),
    	.TMDS_rh( w_tmds_rh ),
    	.TMDS_rl( w_tmds_rl )
    );
    
    altddio_out1 u_ddio1( .datain_h( w_video_clk), .datain_l( w_video_clk), .outclock(w_video_clk5), .dataout( TMDS[1] ) );
    altddio_out1 u_ddio0( .datain_h(~w_video_clk), .datain_l(~w_video_clk), .outclock(w_video_clk5), .dataout( TMDS[0] ) );
    altddio_out1 u_ddio3( .datain_h( w_tmds_bh),   .datain_l( w_tmds_bl),   .outclock(w_video_clk5), .dataout( TMDS[3] ) );
    altddio_out1 u_ddio2( .datain_h(~w_tmds_bh),   .datain_l(~w_tmds_bl),   .outclock(w_video_clk5), .dataout( TMDS[2] ) );
    altddio_out1 u_ddio5( .datain_h( w_tmds_gh),   .datain_l( w_tmds_gl),   .outclock(w_video_clk5), .dataout( TMDS[5] ) );
    altddio_out1 u_ddio4( .datain_h(~w_tmds_gh),   .datain_l(~w_tmds_gl),   .outclock(w_video_clk5), .dataout( TMDS[4] ) );
    altddio_out1 u_ddio7( .datain_h( w_tmds_rh),   .datain_l( w_tmds_rl),   .outclock(w_video_clk5), .dataout( TMDS[7] ) );
    altddio_out1 u_ddio6( .datain_h(~w_tmds_rh),   .datain_l(~w_tmds_rl),   .outclock(w_video_clk5), .dataout( TMDS[6] ) );
    
    endmodule
    

    Вот весь исходный код проекта для платы Марсоход3, который демонстрирует отображение двоичного счетчика на виртуальных светодиодах.

    А вот его видеодемонстрация:


    Мне кажется, что получилось довольно симпатично.

    Таким образом, с помощью виртуальных светодиодов и семисегментных индикаторов мне удалось сохранить значительную часть проекта MIPSfpga при портировании на плату у которой физически нет 32х светодиодов и нет 7-ми сегментных индикаторов.

    Далее я покажу, как проект MIPSfpga загружается в плату:


    На этой видеодемонстрации показано, как загружается ПЛИС платы с ноутбука из среды САПР Quartus Prime и сразу после загрузки ПЛИС подключенный HDMI монитор получает синхронизацию. Затем на ноутбуке компилируется тестовая программа counter и загружается в плату и запускается на процессоре MIPS в FPGA.

    Здесь уже больше примеров программ для MIPS:


    1. Запускается тест памяти программа 04_memtest, потом
    2. исследуется программа связи 05_uart для SoC MIPSfpga и для последовательного порта с ПК,
    3. работает программа 06_timer_irq использующая аппаратные прерывания
    4. 09_adc_0 — это программа тестирующая встроенный в ПЛИС MAX10 АЦП

    Ну и еще мне хотелось бы показать, как можно вести внутрисхемную отладку программ MIPS с помощью внешнего программатора MBFTDI и программ OpenOCD и GDB:


    Подробнее о проекте MIPSfpga в плате Марсоход3 можно прочитать вот здесь.

    В заключении хотел бы высказать благодарность SparF, YuriPanchul, Frantony за их замечательный цикл статей о MIPSfpga. Без этих статей не было бы и этой моей работы.
    • +16
    • 2,2k
    • 5
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 5
      +2
      Хабр — торт.
        +3
        Это победа!
        «У меня не было светодиодов, поэтому я сделал простую встроенную видеокарту и показываю их через HDMI»
          +2
          Норм! Я тоже как-то рисовал семисегментники, только на VGA. Сейчас HDMI стал более актуален. Пора осваивать.
          Скрытый текст
            0
            Я дико извиняюсь, но в чем суть статьи кроме (рекламы?) модуля «виртуальных светодиодов и семисегментных индикаторов»?
            У меня есть 2 платы: отладочная и рабочая, обе от Xilinx, обе Spartan-6, но они разные: на одной slx9, на другой slx45. И понятно, что приходится и ядра пересобирать, и распиновки переназначать, и частоты менять. В моем случае еще и периферийные устройства от разных вендоров.
            Кроме 4го пункта статья сомнительна.
              0
              Иногда без процессорного ядра задача крайне сложно решается на ПЛИС.
              Но процессорное ядро Nios имеет большое количество ограничений, одно из которых то, что оно требует денег. Но на проектах «поиграться» вполне годиться.

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое