这里综合了Altera提供的各种文献和实例,在最新的Quartus 13.1构建。
1. New Project
2.Create New System
Ctrl+R,将时钟Name更改为clk_50,频率为50MHz
加入altpll组件,c0->100MHz,作为系统时钟;c1->100MHz,相位延迟-2ns,作为SDRAM时钟;C2->10MHz,作为其他LCD,LED等时钟;可选C3->65MHz,作为VGA像素时钟。(图就不改了)
在View菜单中,打开Clocks视图,修改时钟名字提高易读性。分别是altpll_sys, altpll_sdram, altpll_io, altpll_vga。
altpll.inclk_interface设置为clk_50,双击altpll的export,导出areset,locked,phasedone。这个locked信号可以做nios的reset
加入NIOS Processor,JTAG UART(IRQ 0)
加入SDRAM controller,导出wire,地址锁定为0x0
各component的clk均为altpll_sys,sdram的Avalon Memory Mapped Slave连接到cpu.data_master和instruction_master。
添加Generic Tri-State Controller,作为Common Flash Interface,名字为ext_flash(和web server app模版名字相同)
添加Tri-State Conduit Bridge作为Flash的端口,连接ext_flash.uas->cpu.data_master,ext_flash.tcm->tristate_conduit_bridge_flash.tcs,导出tristate_conduit_bridge_flash.out
add Triple-Speed Ethernet,名字为tse_mac(web sever模板中的名字),Core Variations: 10/10/100Mb Ethernet MAC,Interface RGMII,Include MDIO Module (MDC/MDIO)
terASIC提供的DE2_115_Web_Server.qsys中Triple-Speed Ethernet的名字有错(13改了名?)。可用文本编辑器修改此qsys文件,查找triple_speed_ethernet,修改module为:
add scatter-gatter dma controller,Memory To Stream,Source error width为1,作为发送DMA
再次add scatter gather dma controller,Stream To Memory,Sink error width为6
tse, descriptor memory, dma时钟都是alt_sys。
tse.control_port->cpu.data_master
tse.receive_clock->altpll_sys
tse.transmit_clock->altpll_sys
接收链路:tse.receive->sgdma_rx.in, sgdma_rx.m_write->sdram.s1
发送链路:sgdma_tx.m_read->sdram.s1, sgdma_tx.out->tse.trnsmit
sgdma_rx, sgdma_tx两者的descriptor read 和descriptor write,都连接到descriptor_memory.s1,->cpu.data_master
sgdma_rx设置irq 2,sgdma_tx设置irq 3
根据提示导出tse的conduits
以上时钟都适用系统时钟,mapped slave都连接到cpu.data_master上,包括altpll.pll_slave
添加Avalon-MM Clock Crossing Bridge,设置适当深度
clock_crossing_bridge.m0_clk->altpll_io,clock_crossing_bridge.s0_clk->altpll_sys,clock_crossing_bridge.s0->cpu.data_master。
除非特别说明,以下系统的低速设备都使用altpll_io和clock_crossing_bridge.m0连接到clk和mapped slave (s1)。
add Interval Timer (IRQ 1), System ID, LCD 16027, LED pio (led_pio), SWITCH pio, Seven Segment Display pio, KEY pio (可将KEY[0]留作全局reset)
这里强调一点:System ID是很重要的一个设备,设定一个常数,和timestamp配合判断NIOS和你的BSP是否匹配,不要在Run Configuration 中采取 Ignore mismatched system timestamp,我常常因为这个 mismatch 的提示才知道bsp不匹配。
修改cpu,reset vector memory 和 exception vector memory 都设置为 sdram.s1
菜单System -> Create Global Reset Network
System -> assign base address
FIle -> Save
应当只有一个警告
Warning: System.flash: Properties (isFlash,isMemoryDevice,isNonVolatileStorage) have been set on interface uas - in composed mode these are ignored
终于可以:Generate -> Generating...
Generate -> HDL example, copy
3. Create a new DDIO_OUT megafunction variation
width 设置为 1bit,Neither asynchronous clear nor asynchronous set ports options.
4. Create a new altpll megafunction variation
输入时钟为以太网的接收时钟,c0:125MHz; c1: 125MHz, 90deg; c2:125MHz, 180deg
5. New systemverilog file
paste HDL example
从terasic提供的例子中copy端口描述部分
修改nios的实例化部分
`define NET0
module web_server(
CLOCK //
CLOCK_50,
CLOCK2_50,
CLOCK3_50,
ENETCLK_25,
Sma //
SMA_CLKIN,
SMA_CLKOUT,
LED //
LEDG,
LEDR,
KEY //
KEY,
SW //
SW,
SEG7 //
HEX0,
HEX1,
HEX2,
HEX3,
HEX4,
HEX5,
HEX6,
HEX7,
LCD //
LCD_BLON,
LCD_DATA,
LCD_EN,
LCD_ON,
LCD_RS,
LCD_RW,
RS232 //
UART_CTS,
UART_RTS,
UART_RXD,
UART_TXD,
PS2 //
PS2_CLK,
PS2_DAT,
PS2_CLK2,
PS2_DAT2,
SDCARD //
SD_CLK,
SD_CMD,
SD_DAT,
SD_WP_N,
VGA //
VGA_B,
VGA_BLANK_N,
VGA_CLK,
VGA_G,
VGA_HS,
VGA_R,
VGA_SYNC_N,
VGA_VS,
Audio //
AUD_ADCDAT,
AUD_ADCLRCK,
AUD_BCLK,
AUD_DACDAT,
AUD_DACLRCK,
AUD_XCK,
I2C for EEPROM //
EEP_I2C_SCLK,
EEP_I2C_SDAT,
I2C for Audio and Tv-Decode //
I2C_SCLK,
I2C_SDAT,
Ethernet 0 //
ENET0_GTX_CLK,
ENET0_INT_N,
ENET0_MDC,
ENET0_MDIO,
ENET0_RST_N,
ENET0_RX_CLK,
ENET0_RX_COL,
ENET0_RX_CRS,
ENET0_RX_DATA,
ENET0_RX_DV,
ENET0_RX_ER,
ENET0_TX_CLK,
ENET0_TX_DATA,
ENET0_TX_EN,
ENET0_TX_ER,
ENET0_LINK100,
Ethernet 1 //
ENET1_GTX_CLK,
ENET1_INT_N,
ENET1_MDC,
ENET1_MDIO,
ENET1_RST_N,
ENET1_RX_CLK,
ENET1_RX_COL,
ENET1_RX_CRS,
ENET1_RX_DATA,
ENET1_RX_DV,
ENET1_RX_ER,
ENET1_TX_CLK,
ENET1_TX_DATA,
ENET1_TX_EN,
ENET1_TX_ER,
ENET1_LINK100,
TV Decoder //
TD_CLK27,
TD_DATA,
TD_HS,
TD_RESET_N,
TD_VS,
/// USB OTG controller
OTG_DATA,
OTG_ADDR,
OTG_CS_N,
OTG_WR_N,
OTG_RD_N,
OTG_INT,
OTG_RST_N,
IR Receiver //
IRDA_RXD,
SDRAM //
DRAM_ADDR,
DRAM_BA,
DRAM_CAS_N,
DRAM_CKE,
DRAM_CLK,
DRAM_CS_N,
DRAM_DQ,
DRAM_DQM,
DRAM_RAS_N,
DRAM_WE_N,
SRAM //
SRAM_ADDR,
SRAM_CE_N,
SRAM_DQ,
SRAM_LB_N,
SRAM_OE_N,
SRAM_UB_N,
SRAM_WE_N,
Flash //
FL_ADDR,
FL_CE_N,
FL_DQ,
FL_OE_N,
FL_RST_N,
FL_RY,
FL_WE_N,
FL_WP_N,
GPIO //
GPIO,
HSMC (LVDS) //
HSMC_CLKIN_P1,
HSMC_CLKIN_P2,
HSMC_CLKIN0,
HSMC_CLKOUT_P1,
HSMC_CLKOUT_P2,
HSMC_CLKOUT0,
HSMC_D,
HSMC_RX_D_P,
HSMC_TX_D_P,
EXTEND IO //
EX_IO
);
//=======================================================
// PARAMETER declarations
//=======================================================
//=======================================================
// PORT declarations
//=======================================================
CLOCK //
input CLOCK_50;
input CLOCK2_50;
input CLOCK3_50;
input ENETCLK_25;
Sma //
input SMA_CLKIN;
output SMA_CLKOUT;
LED //
output [8:0] LEDG;
output [17:0] LEDR;
KEY //
input [3:0] KEY;
SW //
input [17:0] SW;
SEG7 //
output [6:0] HEX0;
output [6:0] HEX1;
output [6:0] HEX2;
output [6:0] HEX3;
output [6:0] HEX4;
output [6:0] HEX5;
output [6:0] HEX6;
output [6:0] HEX7;
LCD //
output LCD_BLON;
inout [7:0] LCD_DATA;
output LCD_EN;
output LCD_ON;
output LCD_RS;
output LCD_RW;
RS232 //
input UART_CTS;
output UART_RTS;
input UART_RXD;
output UART_TXD;
PS2 //
inout PS2_CLK;
inout PS2_DAT;
inout PS2_CLK2;
inout PS2_DAT2;
SDCARD //
output SD_CLK;
inout SD_CMD;
inout [3:0] SD_DAT;
input SD_WP_N;
VGA //
output [7:0] VGA_B;
output VGA_BLANK_N;
output VGA_CLK;
output [7:0] VGA_G;
output VGA_HS;
output [7:0] VGA_R;
output VGA_SYNC_N;
output VGA_VS;
Audio //
input AUD_ADCDAT;
inout AUD_ADCLRCK;
inout AUD_BCLK;
output AUD_DACDAT;
inout AUD_DACLRCK;
output AUD_XCK;
I2C for EEPROM //
output EEP_I2C_SCLK;
inout EEP_I2C_SDAT;
I2C for Audio and Tv-Decode //
output I2C_SCLK;
inout I2C_SDAT;
Ethernet 0 //
output ENET0_GTX_CLK;
input ENET0_INT_N;
output ENET0_MDC;
inout ENET0_MDIO;
output ENET0_RST_N;
input ENET0_RX_CLK;
input ENET0_RX_COL;
input ENET0_RX_CRS;
input [3:0] ENET0_RX_DATA;
input ENET0_RX_DV;
input ENET0_RX_ER;
input ENET0_TX_CLK;
output [3:0] ENET0_TX_DATA;
output ENET0_TX_EN;
output ENET0_TX_ER;
input ENET0_LINK100;
Ethernet 1 //
output ENET1_GTX_CLK;
input ENET1_INT_N;
output ENET1_MDC;
inout ENET1_MDIO;
output ENET1_RST_N;
input ENET1_RX_CLK;
input ENET1_RX_COL;
input ENET1_RX_CRS;
input [3:0] ENET1_RX_DATA;
input ENET1_RX_DV;
input ENET1_RX_ER;
input ENET1_TX_CLK;
output [3:0] ENET1_TX_DATA;
output ENET1_TX_EN;
output ENET1_TX_ER;
input ENET1_LINK100;
TV Decoder 1 //
input TD_CLK27;
input [7:0] TD_DATA;
input TD_HS;
output TD_RESET_N;
input TD_VS;
USB OTG controller //
inout [15:0] OTG_DATA;
output [1:0] OTG_ADDR;
output OTG_CS_N;
output OTG_WR_N;
output OTG_RD_N;
input OTG_INT;
output OTG_RST_N;
IR Receiver //
input IRDA_RXD;
SDRAM //
output [12:0] DRAM_ADDR;
output [1:0] DRAM_BA;
output DRAM_CAS_N;
output DRAM_CKE;
output DRAM_CLK;
output DRAM_CS_N;
inout [31:0] DRAM_DQ;
output [3:0] DRAM_DQM;
output DRAM_RAS_N;
output DRAM_WE_N;
SRAM //
output [19:0] SRAM_ADDR;
output SRAM_CE_N;
inout [15:0] SRAM_DQ;
output SRAM_LB_N;
output SRAM_OE_N;
output SRAM_UB_N;
output SRAM_WE_N;
Flash //
output [22:0] FL_ADDR;
output FL_CE_N;
inout [7:0] FL_DQ;
output FL_OE_N;
output FL_RST_N;
input FL_RY;
output FL_WE_N;
output FL_WP_N;
GPIO //
inout [35:0] GPIO;
HSMC (LVDS) //
input HSMC_CLKIN_P1;
input HSMC_CLKIN_P2;
input HSMC_CLKIN0;
output HSMC_CLKOUT_P1;
output HSMC_CLKOUT_P2;
output HSMC_CLKOUT0;
inout [3:0] HSMC_D;
input [16:0] HSMC_RX_D_P;
output [16:0] HSMC_TX_D_P;
EXTEND IO //
inout [6:0] EX_IO;
//=======================================================
// REG/WIRE declarations
//=======================================================
logic sys_reset_n;
//===== ethernet =====
logic enet_tx_clk_mac;
logic enet_tx_clk_phy;
logic enet_rx_clk_90deg;
logic enet_gtx_clk;
logic enet_rx_clk;
logic ENET0_mdio_in;
logic ENET0_mdio_oen;
logic ENET0_mdio_out;
logic ENET1_mdio_in;
logic ENET1_mdio_oen;
logic ENET1_mdio_out;
logic ena_10_from_mac;
logic eth_mode;
logic set_1k_to_mac;
logic set_10_to_mac;
logic HEX0P;
logic HEX1P;
logic HEX2P;
logic HEX3P;
logic HEX4P;
logic HEX5P;
logic HEX6P;
logic HEX7P;
logic pll_locked;
logic pll_phasedone;
logic[7:0] ssd0, ssd1, ssd2, ssd3;
logic[7:0] ssd4, ssd5, ssd6, ssd7;
logic enet_reset_n;
parameter ctr_width = 20;
logic[ctr_width-1:0] ctr; // Reset counter
// ===== ethernet clock =====
`ifdef NET0
assign enet_rx_clk = ENET0_RX_CLK;
assign ENET0_GTX_CLK = enet_gtx_clk;
`else
assign enet_rx_clk = ENET1_RX_CLK;
assign ENET1_GTX_CLK = enet_gtx_clk;
`endif
// ===== MDIO Tristate
assign ENET0_mdio_in = ENET0_MDIO;
assign ENET0_MDIO = ENET0_mdio_oen ? 1'bz : ENET0_mdio_out;
assign ENET1_mdio_in = ENET1_MDIO;
assign ENET1_MDIO = ENET1_mdio_oen ? 1'bz : ENET1_mdio_out;
// ===== ethernet signal =====
assign ENET0_RST_N = enet_reset_n;
assign ENET1_RST_N = enet_reset_n;
// ===== ethernet control signal define
assign set_1k_to_mac = 1'b0;
assign set_10_to_mac = 1'b0;
assign sys_reset_n = pll_locked;
assign LEDG[8] = sys_reset_n;
assign HEX0[6:0] = ssd0[6:0];
assign HEX1[6:0] = ssd1[6:0];
assign HEX2[6:0] = ssd2[6:0];
assign HEX3[6:0] = ssd3[6:0];
assign HEX4[6:0] = ssd4[6:0];
assign HEX5[6:0] = ssd5[6:0];
assign HEX6[6:0] = ssd6[6:0];
assign HEX7[6:0] = ssd7[6:0];
//=======================================================
// Structural coding
//=======================================================
always_ff@(posedge CLOCK_50 or negedge sys_reset_n) begin
if (!sys_reset_n) begin
enet_reset_n <= 1'b0;
ctr <= 0;
end
else begin
if (ctr == {ctr_width{1'b1}}) begin
enet_reset_n <= 1'b1;// Auto reset phy 1st time
end
else begin
ctr <= ctr + 1;
enet_reset_n <= 1'b0;
end
end
end
enet_rx_pll pll_inst(
.inclk0(enet_rx_clk),
.c0(enet_rx_clk_90deg),
.c1(enet_tx_clk_mac),
.c2(enet_tx_clk_phy)
);
ddio_out ddio_out_inst(
.datain_h(1'b1),
.datain_l(1'b0),
.outclock(enet_tx_clk_phy),
.dataout(enet_gtx_clk)
);
nios_core nios_inst (
.clk_clk (CLOCK_50), // clk.clk
.reset_reset_n (sys_reset_n), // reset.reset_n
.altpll_areset_export (~KEY[0]), // altpll_areset.export
.altpll_locked_export (pll_locked), // altpll_locked.export
.altpll_phasedone_export (pll_phasedone),// altpll_phasedone.export
.altpll_sdram_clk (DRAM_CLK), // sdram_clk.clk
.altpll_vga_clk (VGA_CLK), // sdram_clk.clk
.sdram_addr (DRAM_ADDR), // sdram.addr
.sdram_ba (DRAM_BA), // .ba
.sdram_cas_n (DRAM_CAS_N), // .cas_n
.sdram_cke (DRAM_CKE), // .cke
.sdram_cs_n (DRAM_CS_N), // .cs_n
.sdram_dq (DRAM_DQ), // .dq
.sdram_dqm (DRAM_DQM), // .dqm
.sdram_ras_n (DRAM_RAS_N), // .ras_n
.sdram_we_n (DRAM_WE_N), // .we_n
.flash_tcm_address_out (FL_ADDR), // flash.tcm_address_out
.flash_tcm_read_n_out (FL_OE_N), // .tcm_read_n_out
.flash_tcm_write_n_out (FL_WE_N), // .tcm_write_n_out
.flash_tcm_data_out (FL_DQ), // .tcm_data_out
.flash_tcm_chipselect_n_out (FL_CE_N), // .tcm_chipselect_n_out
.lcd_display_RS (LCD_RS), // lcd.RS
.lcd_display_RW (LCD_RW), // .RW
.lcd_display_data (LCD_DATA), // .data
.lcd_display_E (LCD_EN), // .E
.ledg_export (LEDG[7:0]), // ledg.export
.ledr_export (LEDR), // ledr.export
.sw_export (SW), // sw.export
.key_export (KEY[3:1]), // key.export
.ssd0_export (ssd0), // ssd0.export
.ssd1_export (ssd1), // ssd1.export
.ssd2_export (ssd2), // ssd2.export
.ssd3_export (ssd3), // ssd3.export
.ssd4_export (ssd4), // ssd4.export
.ssd5_export (ssd5), // ssd5.export
.ssd6_export (ssd6), // ssd6.export
.ssd7_export (ssd7), // ssd7.export
// the_tse_mac (RGMII)
`ifdef NET0
.tse_pcs_tx_clock_clk (enet_tx_clk_mac), // tse_pcs_tx_clock.clk
.tse_pcs_rx_clock_clk (enet_rx_clk_90deg), // tse_pcs_rx_clock.clk
.tse_mac_mdio_mdc (ENET0_MDC), // tse_mac_mdio.mdc
.tse_mac_mdio_mdio_in (ENET0_mdio_in),// .mdio_in
.tse_mac_mdio_mdio_out (ENET0_mdio_out),// .mdio_out
.tse_mac_mdio_mdio_oen (ENET0_mdio_oen),// .mdio_oen
.tse_mac_rgmii_rgmii_in (ENET0_RX_DATA),// tse_mac_rgmii.rgmii_in
.tse_mac_rgmii_rgmii_out (ENET0_TX_DATA),// .rgmii_out
.tse_mac_rgmii_rx_control (ENET0_RX_DV), // .rx_control
.tse_mac_rgmii_tx_control (ENET0_TX_EN), // .tx_control
.tse_mac_status_set_10 (set_10_to_mac),// tse_mac_status.set_10
.tse_mac_status_set_1000 (set_1k_to_mac),// .set_1000
.tse_mac_status_eth_mode (eth_mode), // .eth_mode // not use
.tse_mac_status_ena_10 (ena_10_from_mac) // .ena_10 // not use
`else
.tse_pcs_tx_clock_clk (enet_tx_clk_mac), // tse_pcs_tx_clock.clk
.tse_pcs_rx_clock_clk (enet_rx_clk_90deg), // tse_pcs_rx_clock.clk
.tse_mac_mdio_mdc (ENET1_MDC), // tse_mac_mdio.mdc
.tse_mac_mdio_mdio_in (ENET1_mdio_in),// .mdio_in
.tse_mac_mdio_mdio_out (ENET1_mdio_out),// .mdio_out
.tse_mac_mdio_mdio_oen (ENET1_mdio_oen),// .mdio_oen
.tse_mac_rgmii_rgmii_in (ENET1_RX_DATA),// tse_mac_rgmii.rgmii_in
.tse_mac_rgmii_rgmii_out (ENET1_TX_DATA),// .rgmii_out
.tse_mac_rgmii_rx_control (ENET1_RX_DV), // .rx_control
.tse_mac_rgmii_tx_control (ENET1_TX_EN), // .tx_control
.tse_mac_status_set_10 (set_10_to_mac),// tse_mac_status.set_10 // not use
.tse_mac_status_set_1000 (set_1k_to_mac),// .set_1000
.tse_mac_status_eth_mode (eth_mode), // .eth_mode
.tse_mac_status_ena_10 (ena_10_from_mac)// .ena_10 // not use
`endif
);
// Flash Config
assign FL_RST_N = sys_reset_n;
assign FL_WP_N = 1'b1;
///
// LCD config
assign LCD_BLON = 0; // not supported
assign LCD_ON = 1'b1; // alwasy on
logic io_dir;
logic action;
assign io_dir = KEY[0] & action;
///
// GPIO
assign GPIO[17:0] = (io_dir)?GPIO[35:18]:18'hz;
assign GPIO[35:18] = (io_dir)?GPIO[17:0]:18'hz;
///
// HSMC
assign HSMC_D[1:0] = (io_dir)?HSMC_D[3:2]:2'hz;
assign HSMC_D[3:2] = (io_dir)?HSMC_D[1:0]:2'hz;
assign HSMC_TX_D_P = HSMC_RX_D_P;
assign HSMC_CLKOUT_P1 = HSMC_CLKIN_P1;
assign HSMC_CLKOUT_P2 = HSMC_CLKIN_P2;
assign HSMC_CLKOUT0 = HSMC_CLKIN0;
///
// TV
assign TD_RESET_N = TD_VS;
assign action = FL_RY & TD_HS & TD_CLK27 & (TD_DATA == 8'hff);
///
// ps2
assign PS2_CLK = PS2_DAT;
assign PS2_CLK2 = PS2_DAT2;
endmodule
7. assignments -> import assignments。
8. 可以编译了
9. NIOS software builder
New application and BSP from Template
Project Template: Web Server (RGMII)
在main函数入口可以增加
#ifdef LCD_DISPLAY_NAME
lcdDevice = fopen( LCD_DISPLAY_NAME, "w" );
fprintf(lcdDevice, "Booting...\n");
fclose( lcdDevice );
#endif
便于查看启动状态。
编译。
10. 打开 nios_command_shell,注意文件相对路径。(用GUI操作也可以)
将ro_zipfs.zip写入flash。注意location、base、sidp、id timestamp参数在BSP Editor中查看,usbblaster名字也要确认。默认ro_zipfs.zip在software/yourapp/system下。
bin2flash --input="./ro_zipfs.zip" --output="./ro.flashfs_cfi_flash.flash" --location=0x100000 --verbose
nios2-flash-programmer "./ro.flashfs_cfi_flash.flash" --base 0x9000000 --sidp 0xB000140 --id 0x0 --timestamp 1353045137 --device 1 --instance 0 --cable USB-Blaster\ [2-1.5] --erase-all
然后可以下载了
quartus_pgm -m jtag -c 1 -o "p;web_server.sof"
nios2-download app.elf -c USB-Blaster\ [2-1.5] -g
nios2-terminal -c USB-Blaster\ [2-1.5]
模板生成的example中有详细的注释,这里就不做代码解释了。