当前位置:   article > 正文

玄铁C906的FPGA移植

玄铁c906

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

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

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

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

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

先将Non-module Files 设置为global include

将这些文件添加到include

  1. `define NOISA
  2. `include "aq_dtu_cfig.h"
  3. `include "aq_idu_cfig.h"
  4. `include "aq_lsu_cfig.h"
  5. `include "cpu_cfig.h"
  6. `include "sysmap.h"
  7. `include "tdt_define.h"
  8. `include "tdt_dmi_define.h"

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

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

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2023/09/02 17:51:31
  7. // Design Name:
  8. // Module Name: c906_top
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. `include "aq_dtu_cfig.h"
  22. `include "aq_idu_cfig.h"
  23. `include "aq_lsu_cfig.h"
  24. `include "cpu_cfig.h"
  25. `include "sysmap.h"
  26. `include "tdt_define.h"
  27. `include "tdt_dmi_define.h"
  28. module c906_top(
  29. clk_in1_p,
  30. clk_in1_n,
  31. reset,
  32. uart0_sin_rx,
  33. uart0_sout_tx,
  34. b_pad_gpio_porta,
  35. jclk,
  36. jrst_b,
  37. nrst_b,
  38. jtg_tdi,
  39. jtg_tdo,
  40. jtg_tms
  41. );
  42. input clk_in1_p;
  43. input clk_in1_n;
  44. input reset;
  45. //input rst_b;
  46. input uart0_sin_rx;
  47. output uart0_sout_tx;
  48. inout[7:0] b_pad_gpio_porta;
  49. input jclk;
  50. input jrst_b;
  51. input nrst_b;
  52. input jtg_tdi;
  53. output jtg_tdo;
  54. input jtg_tms ;
  55. wire clk_out1;
  56. wire clk_out2;
  57. wire clk_out3;
  58. wire locked;
  59. //instantiate soc
  60. clk_wiz_0 u_clk_wiz_0
  61. (
  62. // Clock out ports
  63. .clk_out1(clk_out1), // output clk_out1
  64. .clk_out2(clk_out2), // output clk_out2
  65. // Status and control signals
  66. .resetn(reset), // input reset
  67. .locked(locked), // output locked
  68. // Clock in ports
  69. .clk_in1_p(clk_in1_p), // input clk_in1_p
  70. .clk_in1_n(clk_in1_n) // input clk_in1_n
  71. );
  72. soc u_soc(
  73. .i_pad_clk ( clk_out1 ),
  74. .i_pad_uart0_sin ( uart0_sin_rx ),
  75. .o_pad_uart0_sout ( uart0_sout_tx ),
  76. .i_pad_jtg_tclk ( jclk ),
  77. .i_pad_jtg_trst_b ( jrst_b ),
  78. .i_pad_jtg_nrst_b ( nrst_b ),
  79. .b_pad_gpio_porta ( b_pad_gpio_porta ),
  80. .i_pad_jtg_tdi ( jtg_tdi ),
  81. .o_pad_jtg_tdo ( jtg_tdo ),
  82. .i_pad_jtg_tms ( jtg_tms ),
  83. .i_pad_rst_b ( reset )
  84. );
  85. endmodule

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

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

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

  1. set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[7]}]
  2. set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[6]}]
  3. set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[5]}]
  4. set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[4]}]
  5. set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[3]}]
  6. set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[2]}]
  7. set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[1]}]
  8. set_property IOSTANDARD LVCMOS33 [get_ports {b_pad_gpio_porta[0]}]
  9. set_property PACKAGE_PIN AK17 [get_ports clk_in1_p]
  10. set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports clk_in1_p]
  11. set_property PACKAGE_PIN AF13 [get_ports jtg_tdi]
  12. set_property IOSTANDARD LVCMOS33 [get_ports jtg_tdi]
  13. set_property PACKAGE_PIN AE11 [get_ports jtg_tdo]
  14. set_property IOSTANDARD LVCMOS33 [get_ports jtg_tdo]
  15. set_property PACKAGE_PIN AE13 [get_ports jtg_tms]
  16. set_property IOSTANDARD LVCMOS33 [get_ports jtg_tms]
  17. set_property PACKAGE_PIN N23 [get_ports reset]
  18. set_property IOSTANDARD LVCMOS33 [get_ports reset]
  19. set_property PACKAGE_PIN AJ11 [get_ports uart0_sin_rx]
  20. set_property IOSTANDARD LVCMOS33 [get_ports uart0_sin_rx]
  21. set_property PACKAGE_PIN AM9 [get_ports uart0_sout_tx]
  22. set_property IOSTANDARD LVCMOS33 [get_ports uart0_sout_tx]
  23. set_property SLEW SLOW [get_ports jtg_tdo]
  24. set_property SLEW SLOW [get_ports uart0_sout_tx]
  25. set_property PACKAGE_PIN AF9 [get_ports {b_pad_gpio_porta[7]}]
  26. set_property PACKAGE_PIN AF8 [get_ports {b_pad_gpio_porta[6]}]
  27. set_property PACKAGE_PIN AE8 [get_ports {b_pad_gpio_porta[5]}]
  28. set_property PACKAGE_PIN AE10 [get_ports {b_pad_gpio_porta[4]}]
  29. set_property PACKAGE_PIN AD10 [get_ports {b_pad_gpio_porta[3]}]
  30. set_property PACKAGE_PIN AP10 [get_ports {b_pad_gpio_porta[2]}]
  31. set_property PACKAGE_PIN AP11 [get_ports {b_pad_gpio_porta[1]}]
  32. set_property PACKAGE_PIN AN11 [get_ports {b_pad_gpio_porta[0]}]
  33. set_property PACKAGE_PIN AJ13 [get_ports jclk]
  34. set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jclk]
  35. set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jclk_IBUF_inst/O]
  36. set_property IOSTANDARD LVCMOS33 [get_ports jclk]
  37. #5M
  38. create_clock -period 200.000 -name jclk -waveform {0.000 100.000} [get_ports jclk]
  39. #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]
  40. #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]
  41. #create_clock -period 50.000 -name jclk -waveform {0.000 25.000} [get_ports jclk]
  42. #20M
  43. 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]
  44. #20M
  45. 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]
  46. #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]
  47. #set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins u_clk_wiz_0/inst/mmcme3_adv_inst/CLKOUT0]]
  48. #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]
  49. #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]
  50. set_property IOSTANDARD LVCMOS33 [get_ports jrst_b]
  51. set_property IOSTANDARD LVCMOS33 [get_ports nrst_b]
  52. set_property PACKAGE_PIN AL8 [get_ports nrst_b]
  53. set_property PACKAGE_PIN AK8 [get_ports jrst_b]
  54. 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集成手册描述了时钟关系

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/220254
推荐阅读
相关标签
  

闽ICP备14008679号