大家好,我们的队伍编号:CICC1068 队名:Neuron Square,这次想分享一下有关E203软核移植的内容。具体如下:
Nulei开发板的顶层代码(e200_opensource-master/fpga/nucleikit/src/system.v
,可以通过在vivado中添加源代码导入全部代码,然后选择system.v为top文件。
这里直接导入人家的工程,IP核肯定是没有例化过的,通过在IP catalog找到时钟IP,将输出时钟定义为16M即可。
由于Genesys2板子上只有一个差分输入的时钟,因此在输入端注意选择差分输入的方式,输入时钟频率为50MHZ。
由于IP核的输出时钟频率有限,在生成MCU SoC的另一个时钟源时,我们采用手写分频器的方式进行。
分频代码如下:
module clk_div(
input clk,
input rst_n,
output reg clk_div
);
parameter NUM_DIV = 11'd1526;
reg [10:0] cnt;
always @(posedge clk or negedge rst_n)
if(!rst_n) begin
cnt <= 11'd0;
clk_div <= 1'b0;
end
else if(cnt < NUM_DIV / 2 - 1) begin
cnt <= cnt + 1'b1;
clk_div <= clk_div;
end
else begin
cnt <= 11'd0;
clk_div <= ~clk_div;
end
endmodule
复位模块同样需经过例化,使用IP核的默认配置即可。顶层模块有两个复位信号,分别是 fpga_rst 和 mcu_rst,位,这两个复位通过一个与操作生成一个为SoC使
用的复位信号。在具体使用时我们可以将其绑定在板子上的KEY按键上,用于复位整个SoC系统。
例化完时钟和复位模块后,我们对顶层模块的子模块端口进行更改,以适配刚刚的时钟和复位,以及Genesys2板子即可。在这里我贴出自己的system.v文件,以供参考:
`timescale 1ns/1ps
module system
(
input wire CLK50MHZ,//GCLK-W19
//input wire CLK32768KHZ,//RTC_CLK-Y18
//input wire CLK50MHZ,
input wire fpga_rst,//FPGA_RESET-T6
input wire mcu_rst,//MCU_RESET-P20
// Dedicated QSPI interface
output wire qspi0_cs,
output wire qspi0_sck,
inout wire [3:0] qspi0_dq,
//gpioA
inout wire [31:0] gpioA,//GPIOA00~GPIOA31
//gpioB
inout wire [31:0] gpioB,//GPIOB00~GPIOB31
// JD (used for JTAG connection)
inout wire mcu_TDO,//MCU_TDO-N17
inout wire mcu_TCK,//MCU_TCK-P15
inout wire mcu_TDI,//MCU_TDI-T18
inout wire mcu_TMS,//MCU_TMS-P17
//pmu_wakeup
inout wire pmu_paden, //PMU_VDDPADEN-U15
inout wire pmu_padrst, //PMU_VADDPARST_V15
inout wire mcu_wakeup //MCU_WAKE-N15
);
wire clk_out1;
wire mmcm_locked;
wire reset_periph;
wire ck_rst;
// All wires connected to the chip top
wire dut_clock;
wire dut_reset;
wire dut_io_pads_jtag_TCK_i_ival;
wire dut_io_pads_jtag_TMS_i_ival;
wire dut_io_pads_jtag_TMS_o_oval;
wire dut_io_pads_jtag_TMS_o_oe;
wire dut_io_pads_jtag_TMS_o_ie;
wire dut_io_pads_jtag_TMS_o_pue;
wire dut_io_pads_jtag_TMS_o_ds;
wire dut_io_pads_jtag_TDI_i_ival;
wire dut_io_pads_jtag_TDO_o_oval;
wire dut_io_pads_jtag_TDO_o_oe;
wire [32-1:0] dut_io_pads_gpioA_i_ival;
wire [32-1:0] dut_io_pads_gpioA_o_oval;
wire [32-1:0] dut_io_pads_gpioA_o_oe;
wire [32-1:0] dut_io_pads_gpioB_i_ival;
wire [32-1:0] dut_io_pads_gpioB_o_oval;
wire [32-1:0] dut_io_pads_gpioB_o_oe;
wire dut_io_pads_qspi0_sck_o_oval;
wire dut_io_pads_qspi0_cs_0_o_oval;
wire dut_io_pads_qspi0_dq_0_i_ival;
wire dut_io_pads_qspi0_dq_0_o_oval;
wire dut_io_pads_qspi0_dq_0_o_oe;
wire dut_io_pads_qspi0_dq_1_i_ival;
wire dut_io_pads_qspi0_dq_1_o_oval;
wire dut_io_pads_qspi0_dq_1_o_oe;
wire dut_io_pads_qspi0_dq_2_i_ival;
wire dut_io_pads_qspi0_dq_2_o_oval;
wire dut_io_pads_qspi0_dq_2_o_oe;
wire dut_io_pads_qspi0_dq_3_i_ival;
wire dut_io_pads_qspi0_dq_3_o_oval;
wire dut_io_pads_qspi0_dq_3_o_oe;
wire dut_io_pads_aon_erst_n_i_ival;
wire dut_io_pads_aon_pmu_dwakeup_n_i_ival;
wire dut_io_pads_aon_pmu_vddpaden_o_oval;
wire dut_io_pads_aon_pmu_padrst_o_oval ;
wire dut_io_pads_bootrom_n_i_ival;
wire dut_io_pads_dbgmode0_n_i_ival;
wire dut_io_pads_dbgmode1_n_i_ival;
wire dut_io_pads_dbgmode2_n_i_ival;
//=================================================
// Clock & Reset
wire clk_8388;
wire clk_16M;
wire CLK32768KHZ;
/*
mmcm ip_mmcm
(
.resetn(ck_rst),
.clk_in1(CLK100MHZ),
.clk_out2(clk_16M), // 16 MHz, this clock we set to 16MHz
.locked(mmcm_locked)
);
*/
//---new---
clk_wiz_0 ip_clk_wiz
(
.clk_out1(clk_16M), // output clk_out1
.resetn(ck_rst), // input resetn
.locked(mmcm_locked), // output locked
.clk_in1(CLK50MHZ)
);
//--------
assign ck_rst = fpga_rst & mcu_rst;
//---new---
clk_div u_32768_clk
(
.clk(CLK50MHZ),
.rst_n(ck_rst),
.clk_div(CLK32768KHZ) //实际32765.4HZ
);
//--------
proc_sys_reset_0 ip_reset_sys
(
.slowest_sync_clk(clk_16M),
.ext_reset_in(ck_rst), // Active-low
.aux_reset_in(1'b1),
.mb_debug_sys_rst(1'b0),
.dcm_locked(mmcm_locked),
.mb_reset(),
.bus_struct_reset(),
.peripheral_reset(reset_periph),
.interconnect_aresetn(),
.peripheral_aresetn()
);
//=================================================
// SPI0 Interface
wire [3:0] qspi0_ui_dq_o;
wire [3:0] qspi0_ui_dq_oe;
wire [3:0] qspi0_ui_dq_i;
PULLUP qspi0_pullup[3:0]
(
.O(qspi0_dq)
);
IOBUF qspi0_iobuf[3:0]
(
.IO(qspi0_dq),
.O(qspi0_ui_dq_i),
.I(qspi0_ui_dq_o),
.T(~qspi0_ui_dq_oe)
);
//=================================================
// IOBUF instantiation for GPIOs
IOBUF
#(
.DRIVE(12),
.IBUF_LOW_PWR("TRUE"),
.IOSTANDARD("DEFAULT"),
.SLEW("SLOW")
)
gpioA_iobuf[31:0]
(
.O(dut_io_pads_gpioA_i_ival),
.IO(gpioA),
.I(dut_io_pads_gpioA_o_oval),
.T(~dut_io_pads_gpioA_o_oe)
);
IOBUF
#(
.DRIVE(12),
.IBUF_LOW_PWR("TRUE"),
.IOSTANDARD("DEFAULT"),
.SLEW("SLOW")
)
gpioB_iobuf[31:0]
(
.O(dut_io_pads_gpioB_i_ival),
.IO(gpioB),
.I(dut_io_pads_gpioB_o_oval),
.T(~dut_io_pads_gpioB_o_oe)
);
//=================================================
// JTAG IOBUFs
wire iobuf_jtag_TCK_o;
IOBUF
#(
.DRIVE(12),
.IBUF_LOW_PWR("TRUE"),
.IOSTANDARD("DEFAULT"),
.SLEW("SLOW")
)
IOBUF_jtag_TCK
(
.O(iobuf_jtag_TCK_o),
.IO(mcu_TCK),
.I(1'b0),
.T(1'b1)
);
assign dut_io_pads_jtag_TCK_i_ival = iobuf_jtag_TCK_o ;
PULLUP pullup_TCK (.O(mcu_TCK));
wire iobuf_jtag_TMS_o;
IOBUF
#(
.DRIVE(12),
.IBUF_LOW_PWR("TRUE"),
.IOSTANDARD("DEFAULT"),
.SLEW("SLOW")
)
IOBUF_jtag_TMS
(
.O(iobuf_jtag_TMS_o),
.IO(mcu_TMS),
.I(1'b0),
.T(1'b1)
);
assign dut_io_pads_jtag_TMS_i_ival = iobuf_jtag_TMS_o;
PULLUP pullup_TMS (.O(mcu_TMS));
wire iobuf_jtag_TDI_o;
IOBUF
#(
.DRIVE(12),
.IBUF_LOW_PWR("TRUE"),
.IOSTANDARD("DEFAULT"),
.SLEW("SLOW")
)
IOBUF_jtag_TDI
(
.O(iobuf_jtag_TDI_o),
.IO(mcu_TDI),
.I(1'b0),
.T(1'b1)
);
assign dut_io_pads_jtag_TDI_i_ival = iobuf_jtag_TDI_o;
PULLUP pullup_TDI (.O(mcu_TDI));
wire iobuf_jtag_TDO_o;
IOBUF
#(
.DRIVE(12),
.IBUF_LOW_PWR("TRUE"),
.IOSTANDARD("DEFAULT"),
.SLEW("SLOW")
)
IOBUF_jtag_TDO
(
.O(iobuf_jtag_TDO_o),
.IO(mcu_TDO),
.I(dut_io_pads_jtag_TDO_o_oval),
.T(~dut_io_pads_jtag_TDO_o_oe)
);
//wire iobuf_jtag_TRST_n_o;
//IOBUF
//#(
// .DRIVE(12),
// .IBUF_LOW_PWR("TRUE"),
// .IOSTANDARD("DEFAULT"),
// .SLEW("SLOW")
//)
//=================================================
// Assignment of IOBUF "IO" pins to package pins
// Pins IO0-IO13
// Shield header row 0: PD0-PD7
// Use the LEDs for some more useful debugging things.
assign pmu_paden = dut_io_pads_aon_pmu_vddpaden_o_oval;
assign pmu_padrst = dut_io_pads_aon_pmu_padrst_o_oval;
// model select
assign dut_io_pads_bootrom_n_i_ival = 1'b1; //
assign dut_io_pads_dbgmode0_n_i_ival = 1'b1;
assign dut_io_pads_dbgmode1_n_i_ival = 1'b1;
assign dut_io_pads_dbgmode2_n_i_ival = 1'b1;
//
e203_soc_top dut
(
.hfextclk(clk_16M),
.hfxoscen(),
.lfextclk(CLK32768KHZ),
.lfxoscen(),
// Note: this is the real SoC top AON domain slow clock
.io_pads_jtag_TCK_i_ival(dut_io_pads_jtag_TCK_i_ival),
.io_pads_jtag_TMS_i_ival(dut_io_pads_jtag_TMS_i_ival),
.io_pads_jtag_TDI_i_ival(dut_io_pads_jtag_TDI_i_ival),
.io_pads_jtag_TDO_o_oval(dut_io_pads_jtag_TDO_o_oval),
.io_pads_jtag_TDO_o_oe (dut_io_pads_jtag_TDO_o_oe),
.io_pads_gpioA_i_ival(dut_io_pads_gpioA_i_ival),
.io_pads_gpioA_o_oval(dut_io_pads_gpioA_o_oval),
.io_pads_gpioA_o_oe (dut_io_pads_gpioA_o_oe),
.io_pads_gpioB_i_ival(dut_io_pads_gpioB_i_ival),
.io_pads_gpioB_o_oval(dut_io_pads_gpioB_o_oval),
.io_pads_gpioB_o_oe (dut_io_pads_gpioB_o_oe),
.io_pads_qspi0_sck_o_oval (dut_io_pads_qspi0_sck_o_oval),
.io_pads_qspi0_cs_0_o_oval(dut_io_pads_qspi0_cs_0_o_oval),
.io_pads_qspi0_dq_0_i_ival(dut_io_pads_qspi0_dq_0_i_ival),
.io_pads_qspi0_dq_0_o_oval(dut_io_pads_qspi0_dq_0_o_oval),
.io_pads_qspi0_dq_0_o_oe (dut_io_pads_qspi0_dq_0_o_oe),
.io_pads_qspi0_dq_1_i_ival(dut_io_pads_qspi0_dq_1_i_ival),
.io_pads_qspi0_dq_1_o_oval(dut_io_pads_qspi0_dq_1_o_oval),
.io_pads_qspi0_dq_1_o_oe (dut_io_pads_qspi0_dq_1_o_oe),
.io_pads_qspi0_dq_2_i_ival(dut_io_pads_qspi0_dq_2_i_ival),
.io_pads_qspi0_dq_2_o_oval(dut_io_pads_qspi0_dq_2_o_oval),
.io_pads_qspi0_dq_2_o_oe (dut_io_pads_qspi0_dq_2_o_oe),
.io_pads_qspi0_dq_3_i_ival(dut_io_pads_qspi0_dq_3_i_ival),
.io_pads_qspi0_dq_3_o_oval(dut_io_pads_qspi0_dq_3_o_oval),
.io_pads_qspi0_dq_3_o_oe (dut_io_pads_qspi0_dq_3_o_oe),
// Note: this is the real SoC top level reset signal
.io_pads_aon_erst_n_i_ival(ck_rst),
.io_pads_aon_pmu_dwakeup_n_i_ival(dut_io_pads_aon_pmu_dwakeup_n_i_ival),
.io_pads_aon_pmu_vddpaden_o_oval(dut_io_pads_aon_pmu_vddpaden_o_oval),
.io_pads_aon_pmu_padrst_o_oval (dut_io_pads_aon_pmu_padrst_o_oval ),
.io_pads_bootrom_n_i_ival (dut_io_pads_bootrom_n_i_ival),
.io_pads_dbgmode0_n_i_ival (dut_io_pads_dbgmode0_n_i_ival),
.io_pads_dbgmode1_n_i_ival (dut_io_pads_dbgmode1_n_i_ival),
.io_pads_dbgmode2_n_i_ival (dut_io_pads_dbgmode2_n_i_ival)
);
// Assign reasonable values to otherwise unconnected inputs to chip top
wire iobuf_dwakeup_o;
IOBUF
#(
.DRIVE(12),
.IBUF_LOW_PWR("TRUE"),
.IOSTANDARD("DEFAULT"),
.SLEW("SLOW")
)
IOBUF_dwakeup_n
(
.O(iobuf_dwakeup_o),
.IO(mcu_wakeup),
.I(1'b1),
.T(1'b1)
);
assign dut_io_pads_aon_pmu_dwakeup_n_i_ival = (~iobuf_dwakeup_o);
assign dut_io_pads_aon_pmu_vddpaden_i_ival = 1'b1;
assign qspi0_sck = dut_io_pads_qspi0_sck_o_oval;
assign qspi0_cs = dut_io_pads_qspi0_cs_0_o_oval;
assign qspi0_ui_dq_o = {
dut_io_pads_qspi0_dq_3_o_oval,
dut_io_pads_qspi0_dq_2_o_oval,
dut_io_pads_qspi0_dq_1_o_oval,
dut_io_pads_qspi0_dq_0_o_oval
};
assign qspi0_ui_dq_oe = {
dut_io_pads_qspi0_dq_3_o_oe,
dut_io_pads_qspi0_dq_2_o_oe,
dut_io_pads_qspi0_dq_1_o_oe,
dut_io_pads_qspi0_dq_0_o_oe
};
assign dut_io_pads_qspi0_dq_0_i_ival = qspi0_ui_dq_i[0];
assign dut_io_pads_qspi0_dq_1_i_ival = qspi0_ui_dq_i[1];
assign dut_io_pads_qspi0_dq_2_i_ival = qspi0_ui_dq_i[2];
assign dut_io_pads_qspi0_dq_3_i_ival = qspi0_ui_dq_i[3];
endmodule
在综合、实现前,我们还需要注意define.v路径在vivado的设置,因为E203软核使用了这些import的模块,需要先预编译define文件才能不报错完成综合。
完成上述所有步骤后,开始后根据板子的约束文件更改,在这里我们未对时序路径进行约束,即可达到建立时间、保持时间的要求,实现后的结果如下:
综合、实现正确。