玄铁C906的FPGA移植

本来准备移植玄铁C910,初步运行发现我的FPGA容量属实不太够,就退而求其次,选择移植选题C906,本人也是第一次移植,因此会出现一些非常傻逼的问题:

我使用的FPGA为XCKU060-FFVA1156-2-I

移植第一步,去玄铁的github上把玄铁C906的开源代码下载下来。

https://github.com/T-head-Semi/openc906

第二步,我们创建vivado工程,导入这两个文件夹里面的所有文件,先不急着关注哪些能用哪些不能用,先全导进去,后面再进行处理

先将Non-module Files 设置为global include

将这些文件添加到include

`define NOISA
`include "aq_dtu_cfig.h"
`include "aq_idu_cfig.h"
`include "aq_lsu_cfig.h"
`include "cpu_cfig.h"
`include "sysmap.h"
`include "tdt_define.h"
`include "tdt_dmi_define.h"

删除不必要的文件,例如:

最后我们可以得到类似于下图的结构,我们可以自己加一个顶层文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/09/02 17:51:31
// Design Name: 
// Module Name: c906_top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
`include "aq_dtu_cfig.h"
`include "aq_idu_cfig.h"
`include "aq_lsu_cfig.h"
`include "cpu_cfig.h"
`include "sysmap.h"
`include "tdt_define.h"
`include "tdt_dmi_define.h"

module c906_top(
    clk_in1_p,
    clk_in1_n,
    reset,
    uart0_sin_rx,
    uart0_sout_tx,
    b_pad_gpio_porta,
    jclk,
    jrst_b,
    nrst_b,
    jtg_tdi,
    jtg_tdo,
    jtg_tms
 );
    input clk_in1_p;
    input clk_in1_n;
    input reset;
    //input rst_b;
    input uart0_sin_rx;
    output uart0_sout_tx;
    inout[7:0] b_pad_gpio_porta;
    input jclk;
    input jrst_b;
    input nrst_b;
    input jtg_tdi;
    output jtg_tdo;
    input jtg_tms ;  
    
    wire clk_out1;
    wire clk_out2;
    wire clk_out3;
    wire locked;
    
    //instantiate soc    
  clk_wiz_0 u_clk_wiz_0
   (
    // Clock out ports
    .clk_out1(clk_out1),     // output clk_out1
    .clk_out2(clk_out2),     // output clk_out2
    // Status and control signals
    .resetn(reset), // input reset
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1_p(clk_in1_p),    // input clk_in1_p
    .clk_in1_n(clk_in1_n)    // input clk_in1_n
);

 soc u_soc(
  .i_pad_clk            ( clk_out1             ),
  .i_pad_uart0_sin      ( uart0_sin_rx         ),
  .o_pad_uart0_sout   	( uart0_sout_tx        ),
  .i_pad_jtg_tclk       ( jclk             ),
  .i_pad_jtg_trst_b     ( jrst_b                ),
  .i_pad_jtg_nrst_b     ( nrst_b                ),
  .b_pad_gpio_porta   	( b_pad_gpio_porta     ),
  .i_pad_jtg_tdi        ( jtg_tdi              ),
  .o_pad_jtg_tdo        ( jtg_tdo              ),
  .i_pad_jtg_tms        ( jtg_tms              ),   
  .i_pad_rst_b          ( reset                )
);

endmodule

我们需要自己添加时钟ip然后对时钟ip进行配置:

接着,我们可以进行端口的绑定和约束的编写

我这里附一个我自己的xdc,其他的可以类似,因为没有用到那些inout口就没有管。

set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[0]}]

set_property PACKAGE_PIN AK17 [get_ports clk_in1_p]
set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports clk_in1_p]
set_property PACKAGE_PIN AF13 [get_ports jtg_tdi]
set_property IOSTANDARD LVCMOS33 [get_ports jtg_tdi]
set_property PACKAGE_PIN AE11 [get_ports jtg_tdo]
set_property IOSTANDARD LVCMOS33 [get_ports jtg_tdo]
set_property PACKAGE_PIN AE13 [get_ports jtg_tms]
set_property IOSTANDARD LVCMOS33 [get_ports jtg_tms]
set_property PACKAGE_PIN N23 [get_ports reset]
set_property IOSTANDARD LVCMOS33 [get_ports reset]
set_property PACKAGE_PIN AJ11 [get_ports uart0_sin_rx]
set_property IOSTANDARD LVCMOS33 [get_ports uart0_sin_rx]
set_property PACKAGE_PIN AM9 [get_ports uart0_sout_tx]
set_property IOSTANDARD LVCMOS33 [get_ports uart0_sout_tx]

set_property SLEW SLOW [get_ports jtg_tdo]
set_property SLEW SLOW [get_ports uart0_sout_tx]

set_property PACKAGE_PIN AF9 [get_ports {b_pad_gpio_porta[7]}]
set_property PACKAGE_PIN AF8 [get_ports {b_pad_gpio_porta[6]}]
set_property PACKAGE_PIN AE8 [get_ports {b_pad_gpio_porta[5]}]
set_property PACKAGE_PIN AE10 [get_ports {b_pad_gpio_porta[4]}]
set_property PACKAGE_PIN AD10 [get_ports {b_pad_gpio_porta[3]}]
set_property PACKAGE_PIN AP10 [get_ports {b_pad_gpio_porta[2]}]
set_property PACKAGE_PIN AP11 [get_ports {b_pad_gpio_porta[1]}]
set_property PACKAGE_PIN AN11 [get_ports {b_pad_gpio_porta[0]}]

set_property PACKAGE_PIN AJ13 [get_ports jclk]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jclk]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jclk_IBUF_inst/O]
set_property IOSTANDARD LVCMOS33 [get_ports jclk]


#5M
create_clock -period 200.000 -name jclk -waveform {0.000 100.000} [get_ports jclk]
#create_clock -period 1000.000 -name u_soc/x_apb/x_apb_bridge/apb_xx_pwrite_reg/Q -waveform {0.000 500.000} [get_pins u_soc/x_apb/x_apb_bridge/apb_xx_pwrite_reg/Q]
#create_clock -period 1000.000 -name u_soc/x_cpu_sub_system_axi/x_c906_wrapper/sys_apb_clk_reg/Q -waveform {0.000 500.000} [get_pins u_soc/x_cpu_sub_system_axi/x_c906_wrapper/sys_apb_clk_reg/Q]
#create_clock -period 50.000 -name jclk -waveform {0.000 25.000} [get_ports jclk]
#20M
create_clock -period 50.000 -name u_soc/x_apb/x_apb_bridge/apb_xx_pwrite_reg/Q -waveform {0.000 25.000} [get_pins u_soc/x_apb/x_apb_bridge/apb_xx_pwrite_reg/Q]
#20M
create_clock -period 50.000 -name u_soc/x_cpu_sub_system_axi/x_c906_wrapper/sys_apb_clk_reg/Q -waveform {0.000 25.000} [get_pins u_soc/x_cpu_sub_system_axi/x_c906_wrapper/sys_apb_clk_reg/Q]
#create_clock -period 50.000 -name u_soc/x_cpu_sub_system_axi/x_c906_wrapper/sys_apb_clk_reg/Q -waveform {0.000 25.000} [get_pins u_soc/x_cpu_sub_system_axi/x_c906_wrapper/sys_apb_clk_reg/Q]
#set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins u_clk_wiz_0/inst/mmcme3_adv_inst/CLKOUT0]]
#set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins u_clk_wiz_0/inst/mmcme3_adv_inst/CLKOUT0]] -group [get_clocks jclk] -group [get_clocks u_soc/x_apb/x_apb_bridge/apb_xx_pwrite_reg/Q] -group [get_clocks u_soc/x_cpu_sub_system_axi/x_c906_wrapper/sys_apb_clk_reg/Q]




#create_clock -period 1000.000 -name u_soc/x_cpu_sub_system_axi/x_c906_wrapper/sys_apb_clk_reg/Q -waveform {0.000 500.000} [get_pins u_soc/x_cpu_sub_system_axi/x_c906_wrapper/sys_apb_clk_reg/Q]

set_property IOSTANDARD LVCMOS33 [get_ports jrst_b]
set_property IOSTANDARD LVCMOS33 [get_ports nrst_b]
set_property PACKAGE_PIN AL8 [get_ports nrst_b]
set_property PACKAGE_PIN AK8 [get_ports jrst_b]

set_false_path -from [get_clocks u_soc/x_apb/x_apb_bridge/apb_xx_pwrite_reg/Q] -to [get_clocks -of_objects [get_pins u_clk_wiz_0/inst/mmcme3_adv_inst/CLKOUT0]]

这时候我们可以进行synthesis,然后可以得到类似于下图结果,由于C906外挂太多存储空间会导致bram爆了:

我们可以对代码进行一定的修改,以降低bram的占用:

①打开x_axi_slave128,将下面例化的两个spsram替换为一个更小的,c906提供了一个f_spsram_32768*12,我们就把原来的换成这个就可以了

②打开mem_ctrl,先将里面例化的ram修改为fpga_ram,然后我们便可以修改里面的MEM_ADDR_WIDTH参数,来降低ram 的宽度

修改完我们再进行systhesis和implementation,便可以得到正确的结果了。

下图便是最后生成的项目的时钟域: 和C906提供的集成手册基本吻合

我们拿cklink对生成的比特流进行测试,可以成功连接上:

后面我写一下在移植过程中遇到的一些问题:

①时钟ip的设置,一定要记得点active low,我之前一直没看到这个,导致cklink连接不上,会报下面所示的错误DMI operation result busy

②本来以为这两个rst只是普通的rst信号,我将其绑到整个c906的rst端口,导致cklink连接报错

 

具体可以去看集成手册软复位的部分

③如果遇到这个问题按照error里的check一一检查,可能是连线问题,也可能是时钟频率的设置问题 C906集成手册描述了时钟关系

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SYT233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值