您当前的位置:首页 > 今日分享头条 > 正文

同步fifo verilog,详解同步FIFO和异步FIFO​

同步fifo verilog,详解同步FIFO和异步FIFO​

1.定义

FIFO是英文First In First Out的缩写,是一种先进先出的数据缓冲区。FIFO和普通存储器的区别在于没有外部的读写地址线,所以使用起来非常简单。但缺点是只能按顺序写入数据,按顺序读出数据,其数据地址由内部读写指针自动加1,无法像普通存储器一样通过地址线读写指定地址。

通常,FIFO用于不同时钟域之间的数据传输。比如FIFO的一端是AD数据采集,另一端是计算机PCI总线。假设其AD采集速率为16位100K SPS,每秒数据量为100K16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度为32bit,最大传输速率为1056Mbps,因此FIFO可以作为两个不同时钟域之间的数据缓冲。此外,FIFO还可以用于不同宽度的数据接口,如单片机的8位数据输出,DSP的16位数据输入。当单片机与DSP相连时,可以利用FIFO来达到数据匹配的目的。

FIFO的分类是基于FIFO工作的时钟域。FIFO可分为同步FIFO和异步FIFO。同步FIFO意味着读时钟和写时钟是同一个时钟。当时钟边沿到来时,读和写操作同时发生。异步FIFO是指读写时钟不一致,读写时钟相互独立。

FIFO设计的难点是如何判断FIFO的空/满状态。为了确保数据的正确写入或读取,而不出现有益或读出状态,需要确保FIFO满时不能被写入。你不能在空的状态下阅读。如何判断FIFO是满还是空,成为FIFO设计的核心问题。

1.同步FIFO的Verilog实现

同步FIFO是指FIFO的读写时钟是同一个时钟,完全异步,不像异步FIFO。同步FIFO的外部接口包括时钟、清零、读请求、写请求、数据输入总线、数据输出总线、空和满信号。同步FIFO的外部接口信号描述如下:

1.时钟,输入,用于同步FIFO读写,上升沿有效;

2.清零,输入,异步清零信号,低电平有效,当该信号有效时,FIFO清零;

3.写请求,输入,低电平有效。当该信号有效时,表示外部电路请求将数据写入FIFO

4.读请求,输入,低电平有效。当该信号有效时,表示外部电路请求从FIFO中读取数据;

5.数据输入总线,输入,当写信号有效时,数据输入总线上的数据写入FIFO

6.数据输出总线,输出,当读信号有效时,从FIFO中读出数据并放到数据输出总线上;

7.空、输出和高电平有效。当该信号有效时,表示FIFO中没有数据,全部为空;

8.满、输出和高电平有效。当该信号有效时,表示FIFO已满,没有空间存储数据。

下面的框图主要描述了同步FIFO的内部结构。画框图有助于理解电路结构,也有助于编写RTL码:

同步FIFO的Verilog代码之一

在modlesim中已经得到验证。

/******************************************************

fifo控制器的verilog描述。

******************************************************/

模块fifo(数据输入、rd、wr、rst、clk、数据输出、满、空);

输入[7:0]数据输入;

输入rd、wr、rst、clk

output[7:0]data out;

输出满,空;

wire[7:0]data out;

reg full_in,empty _ in

寄存器[7:0]存储器[15:0];

reg [3:0] rp,WP;

赋值full=full _ in

赋值empty=empty _ in

//存储器读出

赋值data out=mem[RP];

//存储器写入

总是@(posedge clk)开始

if(wr ~ full _ in)mem[WP]《=datain;

结束

//内存写指针增量

总是@(posedge clk或negedge rst)开始

如果(!rst)WP “=0;

否则开始

if(wr ~ full _ in)WP "=WP 1 ' B1;

结束

结束

//内存读取指针增量

总是@(posedge clk或negedge rst)开始

如果(!rst)RP “=0;

否则开始

if(rd ~ empty _ in)RP =RP 1 B1;

结束

结束

//产生完整信号

总是@(posedge时钟或负边缘rst)开始

如果(!rst)full _ in "=1 B0;

否则开始

if((~ rd wr)((WP==RP-1)| |(RP==4 h0wp==4 HF)))

full _ in =1 'B1;

else if(full _ in rd)full _ in \ u=1 B0;

结束

结束

//生成空信号

总是@(posedge时钟或负边缘rst)开始

如果(!rst)空_入=1 'B1;

否则开始

if((rd ~ wr)(RP==WP-1 | |(RP==4 hfwp==4 h0)))

empty _ in =1 'B1;

否则if(empty _ in wr)empty _ in =1 'B0;

结束

结束

末端模块

…………………………………………………………………………………………………………………………………………………………………………………………。

同步先进先出。比较后进先出法。比较FIFO的Verilog代码之二这一种设计的FIFO,是基于触发器的。宽度,深度的扩展更加方便,结构化跟强。以下代码在modelsim中验证过。

模块fifo_cell (sys_clk,sys_rst_n,read_fifo,write_fifo,fifo_input_data,

next_cell_data,next_cell_full,last_cell_full,cell_data_out,cell _ full);

参数宽度=8;

参数d=2;

输入sys _ clk

输入sys _ rst _ n;

输入读fifo,写fifo

input[WIDTH-1:0]FIFO _ input _ data;

input[WIDTH-1:0]next _ cell _ data;

输入下一个单元已满,最后一个单元已满

output[WIDTH-1:0]cell _ data _ out;

输出单元格_满

reg[WIDTH-1:0]cell _ data _ reg _ array;

reg[WIDTH-1:0]cell _ data _ LD;

reg cell _ data _ ld _ en

reg单元格_满

reg cell _ full _ next

assign cell _ data _ out=cell _ data _ reg _ array;

始终@(posedge sys_clk或negedge sys_rst_n)

如果(!sys_rst_n)

cell _ full &quot=# D 0;

else if (read_fifo || write_fifo)

cell _ full &quot=# D cell _ full _ next

始终@(写先入先出或读先入先出或下一个单元满或最后一个单元满或单元满)

casex({读fifo,写fifo})

2 'b00:cell _ full _ next=cell _ full;

2 'b01:cell _ full _ next=next _ cell _ full;

2 'b10:cell _ full _ next=last _ cell _ full;

2 'b11:cell _ full _ next=cell _ full;

结束案例

始终@(posedge sys_clk或negedge sys_rst_n)

如果(!sys_rst_n)

cell _ data _ reg _ array[WIDTH-1:0]《=# D 0;

else if (cell_data_ld_en)

cell _ data _ reg _ array[WIDTH-1:0]& lt=# D cell _ data _ LD[WIDTH-1:0];

总是@(写先入先出或读先入先出或单元满或最后单元满)

casex({写fifo,读fifo,单元满,最后单元满})

4 'bx1 _ xx:cell _ data _ LD _ en=1 B1;

4 'b10 _ 01:cell _ data _ LD _ en=1 B1;

默认:cell _ data _ ld _ en=1 b0

结束案例

始终@(写先入先出或读先入先出或下一个单元满或单元满或最后一个单元满或先入先出输入数据或下一个单元数据)

casex({写fifo,读fifo,下一个单元满,单元满,最后一个单元满})

5 'b10 _ x01:cell _ data _ LD[宽度-1:0]=FIFO _ input _ data[宽度-1:0];

5 'b11 _ 01x:cell _ data _ LD[宽度-1:0]=FIFO _ input _ data[宽度-1:0];

默认值:cell _ data _ LD[宽度-1:0]=next _ cell _ data[宽度-1:0];

结束案例

末端模块

模块fifo_4cell(sys_clk,sys_rst_n,fifo_input_data,write_fifo,fifo_out_data,

read_fifo、full_cell0、full_cell1、full_cell2、full _ cell 3);

参数宽度=8;

参数d=2;

输入sys _ clk

输入sys _ rst _ n;

input[WIDTH-1:0]FIFO _ input _ data;

output[WIDTH-1:0]FIFO _ out _ data;

输入读fifo,写fifo

输出完整单元0、完整单元1、完整单元2、完整单元3

wire [WIDTH-1:0] dara_out_cell0,data_out_cell1,data_out_cell2,

数据输出单元3、数据输出单元4

线满_单元格4

fifo_cell #(WIDTH,D) cell0

( .sys_clk (sys_clk)。sys_rst_n (sys_rst_n)。FIFO _ input _ data(FIFO _ input _ data[WIDTH-1:0])。write_fifo(写fifo)。下一个单元数据(数据输出单元1[宽度-1:0]),下一个单元满(满单元1),last _ cell _ full(1 b1)。cell _ data _ out(FIFO _ out _ data[WIDTH-1:0])。read_fifo(读fifo)。单元格_满(完整单元0)

);

fifo_cell #(宽度,D)单元格1

( .sys_clk (sys_clk)。sys_rst_n (sys_rst_n)。FIFO _ input _ data(FIFO _ input _ data[WIDTH-1:0])。write_fifo(写fifo)。下一个单元数据(数据输出单元2[宽度-1:0])。下一个单元满(满单元2)。last_cell_full(满单元0)。cell _ data _ out(data _ out _ cell 1[WIDTH-1:0])。read_fifo(读fifo)。cell_full(满单元格1)

);

fifo_cell #(宽度,D) cell2

( .sys_clk (sys_clk)。sys_rst_n (sys_rst_n)。FIFO _ input _ data(FIFO _ input _ data[WIDTH-1:0])。write_fifo(写fifo)。下一个单元数据(数据输出单元3[宽度-1:0])。下一个单元满(满单元3)。last_cell_full(满单元1)。cell _ data _ out(data _ out _ cell 2[WIDTH-1:0])。read_fifo(读fifo)。cell_full(满单元格2)

);

fifo_cell #(宽度,D) cell3

( .sys_clk (sys_clk)。sys_rst_n (sys_rst_n)。FIFO _ input _ data(FIFO _ input _ data[WIDTH-1:0])。write_fifo(写fifo)。下一个单元数据(数据输出单元4[宽度-1:0])。下一个单元满(满单元4)。last_cell_full(满单元2)。cell _ data _ out(data _ out _ cell 3[WIDTH-1:0])。read_fifo(读fifo)。cell_full (full_cell3)

);

赋值data _ out _ cell 4[WIDTH-1:0]={ WIDTH { 1 ' B0 } };

赋值full _ cell4=1 ' b0

末端模块

2.异步FIFO的Verilog实现

FIFO(先进先出队列)是电子系统中广泛使用的一种器件,通常用于缓冲数据和容纳异步信号的频率或相位差。FIFO通常由双口RAM和读写地址产生模块实现。FIFO的接口信号包括异步写时钟(wr_clk)和读时钟(rd_clk),与写时钟同步的写有效(wren)和写数据(wr_data),与读时钟同步的读有效(rden)和读数据(rd_data)。为了实现正确的读写,避免FIFO上溢或下溢,通常要给出与读时钟和写时钟同步的FIFO空标志和满标志,以禁止读写操作。

1异步FIFO功能描述

图1显示了FIFO的接口信号和内部模块图。

如图1所示,写地址生成模块根据写时钟和写有效信号生成增量写眼,读地址生成模块根据读时钟和读有效信号生成增量读地址。FIFO操作如下:在写时钟wr_clk的上升沿,wren有效时,wr_data写入双口RAM中写地址对应的位置;始终将双口RAM中与读地址对应的数据输出到读数据总线。这样就实现了先进先出的功能。

写地址生成模块还根据读地址和写地址之间的关系生成FIFO的满标志。wren有效时,如果写地址2=读地址,full为1;wren无效时,如果写地址1=读地址,full为1。读地址生成模块还根据读地址和写地址之间的差异生成FIFO的空标志。rden有效时,如果写地址-1=读地址,空为1;rden无效时,如果写地址=读地址,空为1。以上述方式产生标志信号,以便提前一个时钟周期产生相应的标志信号。

因为空标志和满标志控制FIFO的操作,标志错误会导致操作错误。如上所述,通过比较读写地址来生成标志。当读写时钟完全不同步时,可能会在比较读写地址时得到错误结果。例如,在改变读地址的过程中,因为读地址的位的变化不同步,所以计算读地址和读地址之间的差可能导致错误的差,从而导致错误的满标志信号。如果将满标志设置为满标志,则应用程序的性能可能会降低,并且数据写入速率可能会降低。但是,当full标志设置为not full时,在执行写操作时可能会出现溢出错误,这在实际应用中是绝对应该避免的。标志信号的产生也可能产生类似的误差。

异步FIFO 2的改进设计

从以上分析中可以看出,异步先进先出。比较后进先出法。比较FIFO之所以会发生错误是国为在地址变化时,由于多位地址各位变化时间不同,异步时钟对其进行采样时数值可能为不同于地址变化丧后数值的其他值,异步产生错误的空标志和满标志,以致于产生先进先出。比较后进先出法。比较FIFO的操作错误。

格雷码是一种在相邻计数值之间只有一位发生变化的编码方式。可以看出,若读写地址采用格雷码编码方式,就可以解决上面的问题。

为了应用的灵活,还增加了两个标志信号,将满(almosf_full)标志和空(几乎_空)标志分别定义如下:当写地址与读地址的距离小于某个预先定义数值时,快满了为1;当读地址与写地址的距离小于这个预先定义的数值时,几乎_空为1。

3异步先进先出。比较后进先出法。比较FIFO的Verilog

……………………………………………………………………………………………………………………………………………………………………………………………………………………………。

异步先进先出。比较后进先出法。比较FIFO的Verilog代码之一

这个是基于随机存取存储的异步先进先出。比较后进先出法。比较FIFO代码,个人认为代码结构简单易懂,非常适合于考试中填写。记得10月份参加威盛的笔试的时候,就考过异步先进先出。比较后进先出法。比较FIFO的实现。想当初要是早点复习,可能就可以通过威盛的笔试了。

与之前的用随机存取存储实现的同步先进先出。比较后进先出法。比较FIFO的程序相比,异步更为复杂。增加了读写控制信号的跨时钟域的同步。此外,判空与判满的也稍有不同。

模块fifo1(rdata、wfull、rempty、wdata、winc、wclk、wrst_n、rinc、rclk、rrst _ n);

参数DSIZE=8;参数ASIZE=4;

output[DSIZE-1:0]rdata;

输出wfull

输出剩余;

input[DSIZE-1:0]wdata;

输入winc、wclk、wrst _ n;

输入rinc、rclk、rrst _ n;

reg wfull,rempty

reg [ASIZE:0] wptr,rptr,wq2_rptr,rq2_wptr,wq1_rptr,rq1 _ wptr

rbin,wbin

reg[DSIZE-1:0]mem[0:(1《ASIZE》-1];

电线,电线

wire [ASIZE:0] rgraynext,rbinnext,wgraynext,wbinnext

电线剩余值,w满载值

//- 双口随机存取存储存储器-

assign rdata=mem[raddr];

始终@(posedge wclk)

如果(winc!w full)mem[waddr]& lt;=wdata

//- 同步rptr指针-

始终@(posedge wclk或negedge wrst_n)

如果(!wrst_n) {wq2_rptr,wq1 _ rptr }》=0;

else {wq2_rptr,wq1_rptr} 《={wq1_rptr,rptr };

//- 同步wptr指针-

始终@(posedge rclk或negedge rrst_n)

如果(!rrst_n) {rq2_wptr,rq1 _ wptr }》=0;

else {rq2_wptr,rq1_wptr} 《={rq1_wptr,wptr };

//- rempty产生与raddr产生-

始终@(posedge rclk或negedge rrst_n) //GRAYSTYLE2指针

开始

如果(!rrst_n) {rbin,rptr } & lt=0;

else {rbin,rptr} 《={rbinnext,rgraynext };

结束

//内存读地址指针(可以使用二进制来寻址内存)

赋值raddr=rbin[ASIZE-1:0];

赋值rbinnext=rbin(rinc ~ rempty);

赋值rgraynext=(rbinnext》1)^ rbinnext;

//当下一个rptr==同步wptr或复位时,FIFO为空

assign rempty _ val=(rgraynext==rq2 _ wptr);

始终@(posedge rclk或negedge rrst_n)

开始

如果(!rrst _ n)remp ty =1 'B1;

else rempty =rempty _ val

结束

//- wfull产生与waddr产生-

始终@(posedge wclk或negedge wrst_n) //GRAYSTYLE2指针

如果(!wrst_n) {wbin,wptr } "=0;

else {wbin,wptr} 《={wbinnext,wgray next };

//内存写地址指针(可以使用二进制来寻址内存)

赋值waddr=wbin[ASIZE-1:0];

赋值wbinnext=wbin(winc ~ w full);

赋值wgray next=(wbinnext》1)^ wbinnext;

赋值w full _ val=(wgray next=={ ~ wq2 _ rptr[ASIZE:ASIZE-1],wq2 _ rptr[ASIZE-2:0]});//:ASIZE-1]

always @(posedge wclk或negedge wrst_n)

如果(!w full "=1 ' B0;

else w full "=w full _ val;

末端模块

………………………………………………………………………………………………………………………………………………………………

异步FIFO的第二个Verilog代码

与之前异步FIFO代码的主要区别在于空/满状态标志的算法不同。

第一种算法:Clifford E. Cummings 文章,构造了一个指针宽度为N 1,深度为2 N字节的FIFO(将格雷码指针转换为二进制指针,方便平方比较)。当指针的最高位的二进制码不一致,而其他N位相等,则FIFO已满(在Clifford E. Cummings 文章,前两位格雷码不一样,后两位LSB一样全,换成二进制表示的MSB也一样)。当指针完全相等时,FIFO为空。

这个方法的思路很清晰。为了比较不同时钟产生的指针,需要将不同时钟域的信号同步到本地时钟域,而使用格雷码的目的就是为了在这个异步同步过程中,将亚稳态的概率降到最低。为什么要构造N 1指针?克利福德卡明斯(Clifford E. Cummings)也解释得很清楚。感兴趣的读者可以看看作者的原文讨论过。Clifford E. Cummings的这篇文章有两个版本,Rev1.1 Rev1.2,两者比较格雷码指针的方法略有不同,Rev1.2版本更简洁。

第二种算法:Clifford E. Cummings 文章。它把FIFO地址分成四部分,每一部分都用高两位的MSB 00,01、 11、 10来判断FIFO是去满还是去空。如果写指针的高两个msb小于读指针的高两个msb,则FIFO几乎满,如果写指针的高两个msb大于读指针的高两个msb,则FIFO几乎空。

它将地址空间分成四个象限(即四个大小相等的区域),然后观察两个指针的相对位置。如果写指针落后读指针一个象限(25%距离,呵呵),证明很可能是满的,否则很可能是空的。此时分别设置两个标志位dirset和dirrst,然后当地址完全相等时,如果dirset有效,则为满,如果dirrst为

这种方法只需要深度为2 N字节的FIFO的N位指针,处理速度比第一种方法快。

这一段是解释的原话,算法一,很好理解。算法二没有似乎不清楚,我不我不太明白。有兴趣的可以查阅论文,详细研究。

总之第二种写法就是推荐的写法。因为异步多时钟设计要按照以下原则来设计:

1.将多时钟逻辑电路(非同步器)尽可能分成多个单时钟模块,有利于静态时序分析工具进行时序验证。

2.同步器应实现为所有输入来自同一时钟域,另一时钟域的异步时钟信号用于数据采样。

3.时钟信号的命名方法可以帮助我们确定那些需要在不同异步时钟域之间处理的信号。

4.当有多个控制信号跨时钟域时,我们必须特别注意这些信号,以确保它们在到达新的时钟域时仍能保持正确的顺序。

模块fifo2 (rdata,wfull,rempty,wdata,

winc、wclk、wrst_n、rinc、rclk、rrst _ n);

参数DSIZE=8;

参数ASIZE=4;

output[DSIZE-1:0]rdata;

输出wfull

输出剩余;

input[DSIZE-1:0]wdata;

输入winc、wclk、wrst _ n;

输入rinc、rclk、rrst _ n;

wire [ASIZE-1:0] wptr,rptr

wire [ASIZE-1:0] waddr,raddr

async_cmp #(ASIZE) async_cmp(。aempty_n(aempty_n)。afull_n(afull_n)。wptr(wptr)。rptr(rptr)。wrst _ n(wrst _ n));

fifomem2 #(DSIZE,ASIZE) fifomem2(。rdata(rdata)。wdata(wdata)。waddr(wptr)。raddr(rptr)。wclken(winc)。wclk(wclk));

rptr_empty2 #(ASIZE) rptr_empty2(.rempty(雷姆普提),rptr(rptr)。aempty_n(aempty_n)。rinc(林克),rclk(rclk)。rrst _ n(rrst _ n));

wptr_full2 #(ASIZE) wptr_full2(.wfull(wfull)。wptr(wptr)。afull_n(afull_n)。winc(winc)。wclk(wclk)。wrst _ n(wrst _ n));

末端模块

模块fifomem2 (rdata、wdata、waddr、raddr、wclken、wclk);

参数DATASIZE=8;//存储器数据字宽度

参数addr size=4;//内存地址位数

参数深度=1”地址大小;//DEPTH=2**ADDRSIZE

output[DATASIZE-1:0]rdata;

输入[DATASIZE-1:0]wdata;

输入[ADDRSIZE-1:0] waddr,raddr

输入wclken、wclk

` ifdef VENDORRAM

//供应商双端口随机存取存储的实例化

供应商_拉姆MEM .dout(rdata).din(wdata)。waddr(waddr).raddr(雷达博士),wclken(wclken),2000 .clk(wclk));

"否则

MEM [0:深度-1];

赋值MEM;

始终@(posedge wclk)

if(wcl ken)MEM[waddr]《=wdata;

` endif

末端模块

模块async_cmp (aempty_n,afull_n,wptr,rptr,wrst _ n);

参数addr size=4;

参数N=地址大小-1;

输出aempty_n,一个全n;

输入[N:0] wptr,rptr

输入wrst _ n;

车辆注册号方向;

电线高=1 'b1

wire dirset _ n=~((wptr[n]^rptr[n-1))~(wptr[n-1]^rptr[n]);

电线dirclr _ n=~((~(wptr[n]^rptr[n-1])(wptr[n-1]^rptr[n])|

~ wrst _ n);

总是@(posedge高电平或负边缘目录集_n或negedge dirclr_n)

如果(!目录名)方向"=1 'b0

else if(!目录集n)方向"=1 'b1

else方向=高;

//always @(negedge dirset_n或negedge dirclr_n)

//如果(!目录名)方向"=1 'b0

//else方向=1 'B1;

赋值aempty_n=~((wptr==rptr)!方向);

分配afull_n=~((wptr==rptr)方向);

末端模块

模块rptr_empty2 (rempty,rptr,aempty_n,rinc,rclk,rrst _ n);

参数addr size=4;

输出剩余;

output[addr size-1:0]rptr;

输入aempty _ n;

输入rinc、rclk、rrst _ n;

寄存器[ADDRSIZE-1:0] rptr,rbin

寄存器rempty,rempty 2;

wire [ADDRSIZE-1:0] rgnext,rbnext

//-

//灰色样式2指针

//-

始终@(posedge rclk或negedge rrst_n)

如果(!rrst_n)开始

rbin =0;

rptr =0;

结束

否则开始

rbin =rbnext

rptr =rg next

结束

//-

//如果不为空,则递增二进制计数

//-

分配rbnext=!rempty?rbin rinc:rbin;

赋值rg next=(Rb next》1)^ Rb next;//二进制到灰度的转换

始终@(posedge rclk或negedge aempty_n)

如果(!aempty_n) {rempty,rempty 2 } & lt=2 'b11

else {rempty,rempty2} 《={rempty2,~ aempty _ n };

末端模块

模块wptr_full2 (wfull,wptr,afull_n,winc,wclk,wrst _ n);

参数addr size=4;

输出wfull

output[addr size-1:0]wptr;

输入一个完整的n;

输入winc、wclk、wrst _ n;

寄存器[ADDRSIZE-1:0] wptr,wbin

寄存器wfull,w full 2;

wire [ADDRSIZE-1:0] wgnext,wbnext

//-

//灰色样式2指针

//-

始终@(posedge wclk或negedge wrst_n)

如果(!开始

wbin =0;

wptr =0;

结束

否则开始

wbin =WB next

wptr =WG next

结束

//-

//如果未满,则递增二进制计数

//-

分配wbnext=!wfull?wbin winc:wbin;

赋值WG next=(WB next》1)^ WB next;//二进制到灰度的转换

始终@(posedge wclk或负边缘wrst_n或negedge afull _ n)

如果(!wrst_n ) {wfull,w full 2 } & lt=2 'b00

else if(!afull_n) {wfull,w full 2 } & lt=2 'b11

else {wfull,wfull2} 《={wfull2,~ a full _ n };

末端模块

日本季刊日本季刊


声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,谢谢。

上一篇: g94珠三角环线高速(珠三角环线高速起点和终点是哪里、全长多少公里)

下一篇: 清华同方是国产电脑吗(中国国内品牌电脑有哪些)



推荐阅读