- A+
前几天遇到一个使用情景,需要从一个包含各个读取代码文件路径及名字的文件中把文件路径提取出来,做一个filelist,这里用到了文本的提取和替换,这里做个小总结记录一下。
从网上找了一个作者写的代码用来练习。
module asyn_fifo #( //parameter declaration parameter ADDR_WIDTH = 4 , parameter DATA_WIDTH = 16 , parameter ALMOST_FULL_GAP = 3 ,//将满,离满还有ALMOST_FULL_GAP时,almost_full有效 parameter ALMOST_EMPTY_GAP = 3 ,//将空,离空还有ALMOST_EMPTY_GAP时,almost_empty有效 parameter FIFO_DEEP = 16 ) ( //fifo write wr_clk , wr_en , almost_full , full , wr_data , //fifo read rd_clk , rd_en , almost_empty, empty , rd_data , wr_reset , rd_reset ); 1)先思考写时钟方向,首先是写请求,在不满且写使能有效拉高写请求. assign wen = wr_en && (!full) 2)其次是写地址, always @(posedge wr_clk or negedge wr_reset) if(!wr_reset) waddr <= {(ADDR_WIDTH+1){1'b0}}; else if(wen) waddr <= waddr + 1'b1; else waddr <= waddr; 3)将写地址转换为格雷码 always @(posedge wr_clk or negedge wr_reset) if(!wr_reset) waddr_gray <= {(ADDR_WIDTH + 1){1'b0}}; else waddr_gray<= waddr^(waddr>>1); 4)将读格雷码转换到写时钟域,准备计算将满和满信号了 always @(posedge wr_clk or negedge wr_reset) if(!wr_reset) begin raddr_gray_sync <= {(ADDR_WIDTH+1){1'b0}}; raddr_gray_sync_d1 <= {(ADDR_WIDTH+1){1'b0}}; end else begin raddr_gray_sync <= raddr_gray; raddr_gray_sync_d1 <= raddr_gray_sync; end 5)将读格雷码转换为二进制(这样有利于将满信号和FIFO usdws(used words,使用了多少字)的计算) integer i; always @(*) begin for(i=0;i<ADDR_WIDTH+1;i=i+1) raddr_gray2bin = ^(raddr_gray_sync_d1>>i); end 6)写地址与读地址间隔计算,写了多少个字了 always @(*)begin if(raddr_gray2bin[ADDR_WIDTH] ^ waddr[ADDR_WIDTH])//二进制扩展位为循环指示位 wr_gap = raddr_gray2bin[ADDR_WIDTH-1:0] - waddr[ADDR_WIDTH-1:0]; else wr_gap = FIFO_DEEP + raddr_gray2bin - waddr; end 7)almost full信号产生 always @(posedge wr_clk or negedge wr_reset)begin if(!wr_reset) almost_full <= 1'b0; else begin if(wr_gap < ALMOST_FULL_GAP) almost_full <= 1'b1; else almost_full <= 1'b0; end end 8)full信号产生 always @(posedge wr_clk or negedge wr_reset)begin if(!wr_reset) full <= 1'b0; else full <= (wr_gap==1)&&wen; 9)再来写读时钟方向,其实与写时钟方向堆成,首先是读请求, assign ren = rd_en &&(!empty); 10)FIFO读地址的产生 always @(posedge rd_clk or negedge rd_reset) if(!rd_reset) raddr <= {(ADDR_WIDTH+1){1'b0}}; else if(ren) raddr <= raddr + 1'b1; else raddr <= raddr; 11)读地址转变为读格雷码 always @(posedge rd_clk or negedge rd_reset) if(!rd_reset) raddr_gray <= {(ADDR_WIDTH + 1){1'b0}}; else raddr_gray <= raddr^(raddr>>1); 12)写地址同步到读时钟域 always @(posedge rd_clk or negedge rd_reset)begin if(!rd_reset) begin waddr_gray_sync <= {(ADDR_WIDTH+1){1'b0}}; waddr_gray_sync_d1 <= {(ADDR_WIDTH+1){1'b0}}; end else begin waddr_gray_sync <= waddr_gray; waddr_gray_sync_d1 <= waddr_gray_sync; end end 13)写地址格雷码变成二进制,便于读格子的计算 integer j; always @(*)begin for(j=0;j<ADDR_WIDTH+1;j=j+1) waddr_gray2bin = ^(waddr_gray_sync_d1>>i); end 14)读格子的计算—即还有多少数据未读 always @(*) rd_gap = waddr_gray2bin - raddr; 15)almost_empty信号产生 always @(posedge rd_clk or negedge rd_reset)begin if(!rd_reset) almost_empty <= 1'b1; else begin if(rd_gap < ALMOST_EMPTY_GAP) almost_empty <= 1'b1; else almost_empty <= 1'b0; end end 16)产生empty信号 always @(posedge rd_clk or negedge rd_reset)begin if(rd_reset) empty <= 1'b1;//复位了FIFO为空 else empty <= (rd_gap == 1) & rd_en; end 17)例化双口RAM,在写请求有效时将数据存放到里面,并在读请求有效时读出数据。 ram ram_inst#( parameter RAM_WIDTH = 4 )( .wr_clk(wr_clk), .addra(wr_addr), .dina(wr_data), .wra(wen), /////// .rd_clk(rd_clk), .addrb(rd_addr), .dina(rd_data), .rdb(ren) );
练习1-将作者写的步骤文字,即x)开头的文字提取出来
使用v/pattern/d来实现,这个命令的意思是将匹配pattern的行提取出来,其中pattern就是你定义的匹配模式,如下图所示。其中^代表匹配行首,d代表匹配一个数字,这样我们就完成了提取。那如果我想删除掉这些而只保留代码呢?
:v/^d/d
我们使用g/pattern/d来实现,这个命令的意思是将匹配pattern的行删除而保留其他。
:g/^d/d
以此类推,重点是会写pattern,这里有个作者已经总结的很好了,可以参考这个作者的总结,已经总结很全了。 https://blog.csdn.net/lazyclough/article/details/6193398
练习3-获取该模块的信号列表(先提取再替换)
第一步:
可以看出信号列表都是以,结尾,除了最后一个,所以可以先复制最后一个信号,然后使用如下命令开始提取。
:v/.*,/d
其中.*分别代表任意字符,任意多个,“,”就是匹配“,”,得到了如下代码。
第二步:
可以看到,还有些以“.”开头的和以“parameter”开头的我们不需要,所以可以使用如下命令去除(这个时候代码已经很少了其实可以用“ndd”删除n行,或者鼠标选中按“d”的方法来操作了,但这里是为了做练习,所以不用它们):
:g/^ss./d
其中^匹配行首,ss匹配两个空格,也可以用s{2},{2}代表匹配两次,.匹配“.”,然后代码如下。
然后输入命令
:g/parameter/d
得到如下代码
第三步:
然后我们需要将“,”全部去除,使用替换命令:range s/pattern/new string/command(其实这列逗号排列是整齐的,可以用列操作很方便的删除,但是我们为了练习)。
:%s/,//g
其中range的%代表全局匹配替换,也可以用行号来指定匹配替换的范围,g代表匹配到的全部替换,gc代表全部替换但是每次替换前要询问。得到的代码如下:
到这里基本就完成了,采用列操作或者上述办法去除掉开头的空格,再把之前复制的最后一个信号复制上去就完成任务。