找回密码
 注册
关于网站域名变更的通知
查看: 368|回复: 2
打印 上一主题 下一主题

简谈FPGA研发设计相关规范(很实用)

[复制链接]

该用户从未签到

跳转到指定楼层
1#
 楼主| 发表于 2024-4-16 15:44 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
今天和大侠聊一聊FPGA研发设计相关规范,养成良好的个人习惯,代码设计风格等,都有助于日后发展。有哪些设计规范,从文档到工程建立等,聊一聊也许你会学到很多东西,少走很多弯路哦。话不多说,上货。: f# _* g2 l8 e4 O4 Z9 l
! @1 ~" W+ r& k5 Y0 W9 Q. K/ i# L  M$ h
        在团队项目开发中,为了使开发的高效性、一致性、正确性,团队应当要有一个规范的设计流程。按照规范来完成项目的设计开发工作,归类清晰明了的工程文件夹级别;项目应拥有良好风格和完整的文档,如设计思路与调试记录及器件选型等;代码书写高效,即统一的书写规范,文件头包含的信息完整,无论自己还是团队他人阅读便一目了然。
4 H" N1 c0 M6 a1 o9 T% R7 @5 x( ?) _5 n! J( Z
一、文档命名:. ?* K7 p' O6 l9 e+ ?; {

8 n: g& u, J2 k9 h$ z
        清晰的文档命名能够让我们思路非常的清晰,所以FPGA工程文件夹的目录要求层次鲜明,归类清晰。一个工程必须要有一个严整的框架结构,用来存放相关的文档、设计,不仅方便自己查看,也提高了项目的团队工作效率。+ D; _8 K& ^' }9 ]; T8 N
* I2 p' N1 Z! e6 Y) C! C" ^* H
下面我们来举例说明:
- }# @: g, q  v1 i4 d: M) n6 f% x9 N( R2 I! e  m- U( J
一级文件夹为工程名<project>
6 e4 O+ f" a4 _& W2 c& s& n0 d
二级文件夹多个:用以存放源文件<src>用以存放Testbench文件<sim>
  R) \$ g; i5 u- c6 p0 i2 B
用来存放设计思路相关类的文件<doc>  用来存放IP 核的文件<core>等等…7 P" i+ d: ]7 P# B0 W7 ]

2 @8 H8 D+ G" U5 _
二、设计文档化:2 a5 b: s# |) z$ A+ q) Q2 p

9 f1 |7 n3 i+ H6 Z
        将自己对设计的思路和调试记录在文档中,有利于以后对模块功能的添加和维护,并且在项目联调时方便项目组其他人员读代码。也方便不同厂家的FPGA之间移植,以及FPGA到ASIC的移植。如下图就是设计文档化的举例说明,文档介绍清晰,功能分析明确,有利于以后对模块功能的添加和维护。
1 y0 t/ u" H, q7 w, S) G1 q: P% V$ S

' M8 Q4 X' N, S
! e4 c8 {3 E5 R2 f. [; z

- J' a$ d4 P9 a. o6 H  S0 O  ?! F

2 ~% a/ t' F6 T7 p% ^1 C1 w4 U! k/ f1 D7 e

& [/ r& T- z% O7 i7 ^+ T9 H6 z+ u/ K

% {- |; \. a6 V8 `  P, s- B7 Y- z& [
设计思路:
) Q% O. c1 z& y- |
按照项目的要求,自顶向下的分成若干模块,分别编写功能。顶层尽量只做行为描述,逻辑描述在底层编写。模块的编写要有硬件电路思维方式,每一个模块的设计都应考虑是否存在该硬件电路,尽量采用同步设计。
2 x$ L4 {& G6 I/ t, `/ N/ v3 `! b
1 }6 r: r" Y, O; f% m9 ^
三、编码风格:
% `9 X- V$ `7 K' R
        每个module应存在于单独的源文件中,源文件名应与其所包含的模块名相同。每个设计都应该有一个完善的文件头,包含公司名称、设计者、设计时间、文件名、所属项目、模块名称及功能、修改记录及版本信息等内容。代码中的标识符采用传统C语言的命名方法,在单词之间用下划线分开,采用有意义,能反应对象特征、作用和性质的单词命名标识符,以此来增强程序的可读性。为避免标识符过于冗长,较长的单词可以适当的缩写。
" A3 F1 z. n- u& K
四、代码规范:
5 K5 y3 [+ G. \% c  u. ?/ g) s; Z6 T

( J( T2 C+ G( Y7 c& K

低电平有效的信号,后缀名要用“_n”,比如低电平有效的复位信号“rst_n”
$ r  w- {& J3 c7 e. i

模块名和信号名统一小写! X# p# i6 a( G- t  b

变量名要小写,如wire、reg、input、output等定义的

变量命名应按照变量的功能用英文简洁表示出来“xxx_xxx_xxx”,避免过长
& @7 Z3 D5 L; v

采用大写字母定义常量参数,参数名小于20个字母,如parameter TIME=20
+ d. N7 J4 R/ ?. S2 j6 e

时钟信号应前缀“clk”,复位信号应前缀“rst”
) P+ k( `7 O7 Q, n4 {  r% H$ q

对于顶层模块的输出信号尽量被寄存
! {5 K, M! ?' S


5 }6 |5 I3 Y3 c+ T

三态逻辑避免在子模块使用,可以在顶层模块使用  

到其它模块的接口信号按:输入、(双向)、输出的顺序定义端口
. d- B+ j9 ~/ [7 Y        一个模块至少要有一个输入、输出,避免书写空模块      

时钟事件的表达式用“posedge”或“negedge”的形式

If语句嵌套不能太多     

建议不要使用include语句   

建议每个模块添加timescale      

代码中给出必要的注释      

每个文件有个一头文件      

每个文件只包含一个模块      

模块名和文件名保持一致   

& B4 o% ?# o  J, y. F" V- C, S6 K+ R

异步复位,用if(xxx==1’b1)  或  if(xxx==1’b0)      

同步时序逻辑的always block中有且只有一个时钟信号,并且在同一个沿动作      

采用同步设计,避免使用异步逻辑  


& `. b( R5 k2 @" T

一般不要将时钟信号作为数据信号的输入      

不要在时钟路径上添加任何buffer      

在顶层模块中,时钟信号必须可见  


! Z; ?" O+ E: t% ]1 ]

不要采用向量定义的方式定义一组时钟信号      

不要在模块内部生成时钟信号,使用pll产生  

) [1 N2 R7 o% H  L

尽量不使用任务      

不使用事件变量      

不使用系统函数      

不使用disable语句   


/ A" b3 W6 D  ^$ b7 e3 ^

尽量不使用forever、repeat、while等循环语句      

不使用不可综合的运算符      


; y# o  X4 K6 k) p1 X

在一个always语句中有且只能有一个事件列表     

移位变量必须是一个常数   


. T$ @! h2 q$ m& d8 l

时序逻辑语块中统一使用非阻塞型赋值      

组合逻辑语块中使用阻塞型赋值

: R7 {5 e; g* x4 i' B1 H
五、注释规则
7 Z. X3 m' G; _# f& r9 n8 h
1、每个文件有一个文件头,文件头中注明文件名、功能描述、引用模块、设计者、设计时间、版权信息以及修改信息等;

8 G+ Z1 S: E3 d0 D& G9 b' g2、对信号、参量、引脚、模块、函数及进程等加以说明,便于阅读与维护,如信号的作用、频率、占空比、高低电平宽度等。用“//”做小于1行的注释,用“/* */”做多于1行的注释。更新的内容要做注释,记录修改原因,修改日期和修改人。
  W( i5 }+ \' V
六、模块规则) V& N7 y' y6 q% t% I$ [8 x: m
# f1 Z+ X" N/ c+ T( @. p0 h" t
1、module例化名用u_xx_x标示;
' l! z; v8 X3 ^. L. L2、建议给每个模块要加timescale;0 R" c; x) ?0 U0 }3 ^
3、不要书写空的模块,即:一个模块至少要有一个输入和一个输出;
" f8 q! d+ a: T6 ]/ Y8 X7 z. i4、为了保持代码的清晰、美观和层次感,一条语句应占用一行,每行限制在80个字符以内,如果较长(超出80个字符)则换行;6 m( Y& [* i: y! n
5、采用基于名字(name_based)的调用而不是基于顺序的(order_based)的调用;
  _1 j( M6 w. N: ]* X4 E4 z0 V- u6、模块的接口信号按输入、双向、输出顺序定义;
% u; O: B' a: _; o9 ~$ d! f7、使用降序定义向量有效位顺序,最低位为0;6 F, f5 [* O$ n7 U! `1 W. o
8、管脚和信号说明部分:一个管脚和一组总线占用一行,说明要清晰;
/ i* m: a4 j5 t# e1 q. A9、不要采用向量的方式定义一组时钟信号;. z+ \) R) D% e5 w" M
10、逻辑内部不对input进行驱动,在module内不存在没有驱动源的信号,更不能在模块端口存在没有驱动的输出信号,避免在elabarate和compile时产生warning;
& G# j0 A# b) a! W. A! j) f11、在顶层模块中,除了内部的互连和module的例化外,避免在做其他逻辑;
6 m, L' y5 U; \7 p# C; _0 P12、出于层次设计和同步设计的考虑,子模块输出信号建议用寄存器;
7 j8 y$ v4 q6 f! q( i0 d13、内部模块端口避免inout,最好在最顶层模块处理双向总线;
' z( D  q" k) V! `14、子模块中禁止使用三态逻辑,可以在顶层模块使用;" ^! _) n8 f& S6 y! ]$ o
15、禁止出现未连接的端口;$ ?0 G& r0 I! \: H
16、为逻辑升级保留的无用端口和信号要注释;对于层次化设计的逻辑,在升级中采用增量编译;建议采用层次化设计,模块之间相对独立。

! _0 n9 t* P- F七、线网和寄存器规则
7 O: |& Q' t( O7 g3 H5 q5 j9 [0 ?- x
1、锁存器和触发器不允许在不同的always块中赋值,造成多重驱动;
; [- |# l+ n  E% z/ O) b2、出于功能仿真考虑,非阻塞赋值应该增加单位延时,对于寄存器类型的变量赋值时,尤其要注意这一点;阻塞赋值不允许使用单位延时;
' Q" |( o+ C. l9 A+ Q4 ?' q5 V' i3、always语句实现时序逻辑采用非阻塞赋值;always语句实现的组合逻辑和assign语句块中使用阻塞赋值;4、同一信号赋值不能同时使用阻塞和非阻塞两种方式;
6 g; ?+ r  R( }1 s& X5、不允许出现定义了parameter、wire、reg却没有使用的情况;
+ B8 |. S- u& M; `6 {" j5 ~$ E6、不建议使用integer类型寄存器;
6 G4 }1 g/ j8 G7、寄存器类型的信号要初始化;9 _) {: C# g" e: w
8、除移位寄存器外,每个always语句只对一个变量赋值,尽量避免在一个always语句出现多个变量进行运算或赋值。

- Q6 e" B6 f8 h9 y, `& t8 v* F八、表达式规则
# N* N# T: {8 f2 F
5 \% q2 F) j- _9 g6 l1、在表达式内使用括号表示运算的优先级,一行中不能出现多个表达式;+ O, x; A. P2 A
2、不要给信号赋“x”态,以免x值传递;
. Y% E' E3 z5 o6 e$ V3、设计中使用到的0,1,z等常数采用基数表示法书写(即表示为1'b0,1'b1,1'bz或十六进制);
) Q2 [- o- V/ k4、端口申明、比较、赋值等操作时,数据位宽要匹配。

( ?% {6 N# M) g+ Z3 I' o8 _) n" g2 A

; `7 ?5 L6 m" o* i) O1 D九、条件语句规则

; b; \5 n# e, P) z1 }1、if 都有else和它对应,变量在if-else或case语句中所有变量在所有分支中都赋值;
2、如果用到case语句,记得default项;
3、禁止使用casex,case语句item必须使用常数;
4、不允许使用常数作为if语句的条件表达式;
5、条件表达式必须是1bit value;
6、如异步复位:高电平有效使用“if(asynch_reset==1'b1)”,低电平“if(asynch_reset==1'b0)”,不要写成:“if(!asynch_reset)”或者“if(asynch_reset==0)”;

# F( Y! q( c* w5 P( D3 b# u! U- I7、不推荐嵌套使用5级以上if…else if…结构。

1 g9 `" D5 o; ]十、可综合部分规则

, f* Y: ?$ W$ n$ D% Z* F$ Z
1 W% a- H1 y) s5 X* M2 [
1、不要使用include语句;
2、不要使用disable、initial等综合工具不支持的电路,而应采用复位方式进行初始化,但在testbench电路中可以使用;
3、不使用specify模块,不使用===、!==等不可综合的操作符;
4、除仿真外,不使用fork-join语句;
5、除仿真外,不使用while语句;
6、除仿真外,不使用repeat语句;
7、除仿真外,不使用forever语句;
8、除仿真外,不使用系统任务($);
9、除仿真外,不使用deassign语句;
10、除仿真外,不使用force,release语句;
11、除仿真外,不使用named events语句;不在连续赋值语句中引入驱动强度和延时;
12、禁止使用trireg型线网;
13、制止使用tri1、tri0、triand和trior型的连接;
14、不要给驱动supply0和supply1型的线网赋值;
15、设计中不使用macro_module;
16、不要在RTL代码中实例化门级单元,其下列单元:(CMOS/RCOMS/NMOS/PMOS/RNMOS/RPMOS/trans/rtrans/tranif0/tranif1/rtranif0/tranif1/pull_gate)。

8 P- H+ W" {% Q) i: G

9 s" I1 B- Y" W3 Y+ Z十一、可重用部分规则

- `* y1 G* j6 O1 l1、考虑未使用的输入信号power_down,避免传入不稳定态;
2、接口信号尽量少,接口时序尽量简单;
3、将状态机(FSM)电路与其它电路分开,便于综合和后端约束;
4、将异步电路和同步电路区分开,便于综合和后端约束,将相关的逻辑放在一个模块内;
5、合理划分设计的功能模块,保证模块功能的独立性;
6、合理划分模块的大小,避免模块过大;
7、在设计的顶层(top)模块,将I/O口、Boundary scan电路、以及设计逻辑(corelogic)区分开。

- s( O* `* `+ ^' o0 w" J( }+ t) u十二、同步设计规则

$ ~# S" q( U% V, ]9 `& X1、同一个module中,要在时钟信号的同一个沿动作;
2、如果必须使用时钟上升沿和时钟下降沿,则要分两个module设计;
3、在顶层模块中,时钟信号必须可见,不在模块内部生成时钟信号,而要使用DCM/PLL产生的时钟信号;
4、避免使用门控时钟和门控复位;
5、同步复位电路,建议在同一时钟域使用单一的全局同步复位电路;异步复位电路,建议使用单一的全局异步复位电路;
6、不在时钟路径上添加任何buffer;
7、不在复位路径上添加任何buffer;
8、避免使用latch;
9、寄存器的异步复位和异步置位信号不能同时有效;
10、避免使用组合反馈电路;
11、always有且仅有一个的敏感事件列表,敏感事件列表要完整,否则可能会造成前后仿真的结果不一致;
12、异步复位情况下需要异步复位信号和时钟沿做敏感量,同步复位情况下只需要时钟沿做敏感量;
13、时钟事件的表达式要用:“negedge<clk_name>”或“posedge<clock_name>”的形式;
14、复杂电路将组合逻辑和时序逻辑电路分成独立的always描述。
: Z1 g9 s: I! U8 J$ A
十三、循环语句规则

& r5 t8 Q3 d& B1 l' n1、在设计中不推荐使用循环语句;
2、在非常有必要使用的循环语句时,可以使用for语句。

! g" L4 p; E7 @* h$ \! G
3 ]+ g4 I8 @6 n6 C6 H. Z3 E
十四、约束规则
9 f% ^: }, }; t4 g' Y
1、对所有时钟频率和占空比都进行约束;
2、对全局时钟skew进行约束;
3、对于时序要求的路径需要针对特殊要求进行约束,如锁相环鉴相信号;
4、要根据输出管脚驱动要求进行约束,包括驱动电流和信号边沿特性;
5、要根据输入和输出信号的特性进行管脚上下拉约束;
6、针对关键I/O是否约束了输入信号和输入时钟的相位关系,控制输入信号在CLK信号之后或之前多少ns到达输入pad;
7、综合设置时,fanout建议设置为3030;
8、要使用输入输出模块中的寄存器,如Xinlinx公司的IOB,map properties选项pack I/O register/latches into IOBsactor需要设置成为“for input and output”,这样可以控制管脚到内部触发器的延时时间;
9、布局布线报告中IOB、LUTs、RAM等资源利用率应小于百分之八十;
10、对于逻辑芯片对外输入接口,进行tsu/th约束;对于逻辑芯片对外输出接口,进行约束。
  Q& J0 K, X+ {, ]4 `( W* m( m
十五、PLL/DCM4 h; c) I9 T. m7 }! l; P

( K- v/ s$ a! ~2 e1、如果使用FPGA内部DCM和PLL时,应该保证输入时钟的抖动小于300ps,防止DCM/PLL失锁;如果输入时钟瞬断后必须复位PLL/DCM。

5 j1 G% }; J7 x/ q  D( {: V
2、对于所有厂家的FPGA,其片内锁相环只能使用同频率的时钟信号进行锁相,如果特殊情况下需要使用不同频率的信号进行锁相,需要得到厂家的认可,以避免出时钟。

2 p3 }% E4 F/ a- ?5 u; e' }6 @十六、代码编辑

; t7 d2 K( o# O3 {( n* x由于不同编辑器处理不同,对齐代码使用空格,而不是tab键。
9 \+ ]/ m8 X9 B2 Y
***可综合和不可综合详解***
0 V& @1 W: p- }" k+ B
(1)所有综合工具都支持的结构:always,assign,begin,end,case,wire,tri,aupply0,supply1,reg,integer,default,for,function,and,nand,or,nor,xor,xnor,buf,not,        bufif0,bufif1,notif0,notif1,if,inout,input,instantitation,module,negedge,posedge,operators,output,parameter。
2 ]' }+ M8 \- i, ?( R+ r" }! o
(2)所有综合工具都不支持的结构:time,defparam,$finish,fork,join,initial,delays,UDP,wait。

- W. q& n- S- {(3)有些工具支持有些工具不支持的结构:casex,casez,wand,triand,wor,trior,real,disable,forever,arrays,memories,repeat,task,while。
: F/ _+ D( D; Z" @
建立可综合模型的原则
7 H+ b' O7 D0 K+ W3 O' [$ d) F  Q" v) H- Q; ?: C/ F, h9 R. X
要保证Verilog HDL赋值语句的可综合性,在建模时应注意以下要点:+ \) E+ i+ o6 G
& U' f" ]6 E) R1 _% b
(1)不使用initial。
(2)不使用#10。   
(3)不使用循环次数不确定的循环语句,如forever、while等。  
(4)不使用用户自定义原语(UDP元件)。   
(5)尽量使用同步方式设计电路。
(6)除非是关键路径的设计,一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。   
(7)用always过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号。   
(8)所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位。   
(9)对时序逻辑描述和建模,应尽量使用非阻塞赋值方式。对组合逻辑描述和建模,既可以用阻塞赋值,也可以用非阻塞赋值。但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值。   
(10)不能在一个以上的always过程块中对同一个变量赋值。而对同一个赋值对象不能既使用阻塞式赋值,又使用非阻塞式赋值。  
(11)如果不打算把变量推导成锁存器,那么必须在if语句或case语句的所有条件分支中都对变量明确地赋值。 (12)避免混合使用上升沿和下降沿触发的触发器。   
(13)同一个变量的赋值不能受多个时钟控制,也不能受两种不同的时钟条件(或者不同的时钟沿)控制。  
(14)避免在case语句的分支项中使用x值或z值。

5 {' a& o* P% d% f; V1、initial
只能在test bench中使用,不能综合。(用ISE9.1综合时,有的简单的initial也可以综合,不知道为什么)  

% n0 R. c7 \  }) C/ u! E2、events                        
event在同步test bench时更有用,不能综合。

1 f( u6 `$ |/ D/ f0 D3、real                       7 d  z0 c2 ^- I7 U* T7 R' k
不支持real数据类型的综合。+ j7 C" J' c+ l/ C

8 l* j, U+ D- g9 N( d4、time                           - {" A# p5 A: l6 i. Y3 c
不支持time数据类型的综合。
0 K% V- E$ l/ o( t: f1 V' C+ R) B- o1 }4 T" W
5、force 和release      
% b* J8 u0 V, Q. N$ }" p( {不支持force和release的综合。
( k( Y; c, n. S4 C* S
0 U7 \4 N( x4 b- E* a$ N* w6、assign 和deassign      % F7 _' U; D, J) v4 F+ O
不支持对reg 数据类型的assign或deassign进行综合,支持对wire数据类型的assign或deassign进行综合。
" m  }% }+ B, G
7、fork join                     
不可综合,可以使用非块语句达到同样的效果。      

+ l# ?: m. E3 b, y% ]! _$ ?% G
8、primitives               
# k, i' v6 {5 {支持门级原语的综合,不支持非门级原语的综合。+ U$ t( b$ l- b

, ?1 h/ `) q$ d0 u9、table                    . W& l: a3 x0 `) _. `7 b$ T
不支持UDP 和table的综合。* F5 p% J6 A7 I) x& K0 r" I, y1 c

" n+ r+ d* F6 v7 V! d8 a10、敏感列表里同时带有posedge和negedge
) w+ @0 F- }5 X* a0 C2 I6 |% e( M- L2 I9 I; G! b
如:always @(posedge clk or negedge clk) begin...end这个always块不可综合。7 N) m. T0 t2 S) R: Z
4 T7 t) Z. }4 w' C5 O2 h+ c9 D: s
11、同一个reg变量被多个always块驱动
& Q( |' F* O- M8 v, r- X, {# H( }, c* V) \# ]
12、延时
/ R9 Z+ d; U0 D: b2 s
8 K; N" h* Q$ t$ Z) `+ b以#开头的延时不可综合成硬件电路延时,综合工具会忽略所有延时代码,但不会报错。' s2 t) u  L- Q  w0 l' ~4 S
如:a=#10 b;- j; h; R' h9 L/ i# m) ], o
这里的#10是用于仿真时的延时,在综合的时候综合工具会忽略它。也就是说,在综合的时候上式等同于a=b;
) x) J) m+ ]8 T2 T" _3 b1 S
1 r, d' j+ [! x) d: e- E& n13、与X、Z的比较
& e, h: f& P! K
3 p2 V; W: L* }6 ^4 }& O# V. M* a可能会有人喜欢在条件表达式中把数据和X(或Z)进行比较,殊不知这是不可综合的,综合工具同样会忽略。所以要确保信号只有两个状态:0或1。
4 \" r( k& y5 h2 X8 {1 q; T5 G
如:
. G5 ?" r, F8 P" C6 ^

$ }: z. |9 q1 i* p3 F( `& A" t/ V" D
        以上是个人整理出来的一些设计规范,有些部分有重复,但无伤大雅,适用于FPGA Verilog HDL设计,VHDL的话设计思想是一样,大同小异,大家可以举一反三。

( F; ]9 C9 C# n% j
        后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。

  o5 F2 ]) D6 B( J
大侠们,江湖偌大,继续闯荡,愿一切安好,有缘再见!

8 g$ K8 w+ t4 O; ]
  • TA的每日心情

    2019-11-20 15:16
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2024-4-17 16:04 | 只看该作者
    有开发板吗?
  • TA的每日心情
    开心
    2025-7-18 15:39
  • 签到天数: 1131 天

    [LV.10]以坛为家III

    3#
    发表于 2024-4-18 15:21 | 只看该作者
    很有指导价值,内容全面详尽,讲的很透彻和深度,学下
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-7-18 23:46 , Processed in 0.156250 second(s), 26 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表