跨时钟域(不知道长度信息)

上篇文章的异步fifo知道了长度信息,这次采用fifo存储长度信息,ram存储信号。

// An highlighted block
    
module  fifo_ram (
    input               i_per_clk       ,
    input               i_per_rst       ,
    input  [11:0]       i_per_data      ,
    input               i_per_last      ,
    input               i_per_valid     ,
    output              o_per_ready     ,

    input               i_post_clk      ,
    input               i_post_rst      ,
    output [11:0]       o_post_data     ,
    output              o_post_last     ,
    output              o_post_valid    ,  
    input               i_post_ready    
/*-----------------*USER INTERFACE*-----------------*/
    
    
/*-----------------*DRIVE INTERFACE*-----------------*/
    
    
);
/*-----------------*function*-----------------*/
    
    
/*-----------------*parameter*----------------*/
    
    
/*-----------------*port*---------------------*/
    
    
/*-----------------*mechine*------------------*/
    
    
/*-----------------*reg*----------------------*/
    
  reg           [ 6:0]         r_ram_addr_A      ;
  reg           [ 6:0]         r_ram_addr_B    =0;
  reg                          ro_per_ready      ;
  reg           [11:0]         r_per_len       =0;
  reg                          ri_per_last=0     ;
  reg                          ro_post_valid  =0   ;
  reg                          ro_post_last=0      ;
  reg                          r_data_rdb      =0;
  reg                          r_fifo_len_rd_en=0  ;
  reg           [11:0]         r_read_cnt      =0;
  reg                          r_fifo_len_wr_en=0;
  reg                          r_ram_data_rd  =0   ;
  reg                          r_ram_data_rd_1d=0  ;
  reg                          r_ram_data_rd_2d=0  ;
  reg     [11:0]    ro_post_data ;

  
  

/*-----------------*wire*---------------------*/
wire         [11:0]             w_ram_doutb;

wire          [11:0]         w_fifo_len_dout   ;
wire                         w_fifo_len_full   ;
wire                         w_fifo_len_empty  ;

/*-----------------*assign*-------------------*/
assign w_per_active = i_per_valid & o_per_ready ;  
assign w_post_active = o_post_valid & i_post_ready;
assign o_per_ready=ro_per_ready;
assign  o_post_valid=ro_post_valid;
assign o_post_last=ro_post_last;
assign  o_post_data =ro_post_data  ;  
/*-----------------*component*----------------*/


fifo_generator_0 your_12x64_u0 (
  .wr_clk                           (i_per_clk        ),// input wire wr_clk
  .rd_clk                           (i_post_clk       ),// input wire rd_clk
  .din                              (r_per_len        ),// input wire [11 : 0] din
  .wr_en                            (r_fifo_len_wr_en      ),// input wire wr_en

  .rd_en                            (r_fifo_len_rd_en  ),// input wire rd_en
  .dout                             (w_fifo_len_dout  ),// output wire [11 : 0] dout
  .full                             (w_fifo_len_full  ),// output wire full
  .empty                            (w_fifo_len_empty ) // output wire empty
);
    
ram_12x100 ram_12x100_u0 (
  .clka                             (i_per_clk        ),// input wire clka
  .ena                              (i_per_valid       ),// input wire ena
  .wea                              (i_per_valid       ),// input wire [0 : 0] wea
  .addra                            (r_ram_addr_A     ),// input wire [6 : 0] addra
  .dina                             (i_per_data      ),// input wire [11 : 0] dina
  .douta                            (                 ),// output wire [11 : 0] douta

  .clkb                             (i_post_clk       ),// input wire clkb
  .enb                              (r_ram_data_rd       ),// input wire enb
  .web                              (0                ),// input wire [0 : 0] web
  .addrb                            (r_ram_addr_B     ),// input wire [6 : 0] addrb
  .dinb                             (0                ),// input wire [11 : 0] dinb
  .doutb                            (w_ram_doutb      ) // output wire [11 : 0] doutb
);
    
    
/*-----------------*always*-------------------*/
        
/*-----------------*per信号*-------------------*/


//数据开始写入
always @(posedge i_per_clk , posedge i_per_rst) 
begin
 if(i_per_rst)
 begin
    r_ram_addr_A<='d0;
 end   else if(i_per_last) begin
   r_ram_addr_A<='d0;
 end else if(i_per_valid) begin
    r_ram_addr_A<=r_ram_addr_A+1;
 end else begin
    r_ram_addr_A<='d0;
 end
end 


always@(posedge i_per_clk)  //和addr a保持同步
begin
    if(i_per_valid)
    r_per_len <= r_ram_addr_A;
    else 
    r_per_len <= r_per_len;
end
                    


always@(posedge i_per_clk)
begin
   ri_per_last<=i_per_last;
end

//把长度信息写入进去  为w_fifo_len_dout
always@(posedge i_per_clk)
begin
   if (i_per_last & !ri_per_last) begin  //检测上升沿
      r_fifo_len_wr_en<='d1;
   end  else begin
      r_fifo_len_wr_en<='d0;
   end
end
//fifo写入之后开始读取 (这个工作属于下一个时钟的工作) 
/*-------post--------------------*/

always@(posedge i_post_clk)
begin
    if(!w_fifo_len_empty)  //读取到w_fifo_len_dout
    r_fifo_len_rd_en <= 'd1;
    else 
      r_fifo_len_rd_en <= 'd0;
end


always@(posedge i_post_clk)
begin
    if(r_read_cnt == w_fifo_len_dout)    
        r_read_cnt <= 'd0;
    else if(r_ram_data_rd)       
        r_read_cnt <= r_read_cnt + 1;
    else 
        r_read_cnt <= r_read_cnt;
end


always @(posedge i_post_clk , posedge i_post_rst) 
begin
 if(r_read_cnt == w_fifo_len_dout)
 begin
   r_ram_data_rd<='d0;
 end else if( r_fifo_len_rd_en) begin  //读取的信号
   r_ram_data_rd<='d1;
 end else begin
   r_ram_data_rd<=r_ram_data_rd;
 end
end

always @(posedge i_post_clk ) 
begin

      r_ram_data_rd_1d<=r_ram_data_rd;
      r_ram_data_rd_2d<=r_ram_data_rd_1d;
      ro_post_data  <=w_ram_doutb;
end
//ram 读潜伏期 +ro_data赋值一个周期 
always @(posedge i_post_clk) 
begin
   if( !r_ram_data_rd_1d & r_ram_data_rd_2d)//down
   begin
      ro_post_valid<='d0;
   end else if(r_ram_data_rd_1d & !r_ram_data_rd_2d) begin   //up
      ro_post_valid<='d1;
   end else begin
      ro_post_valid<=ro_post_valid;         
   end
end
 //观察到rd的下降沿作为一个条件
always @(posedge i_post_clk ) 
begin
   if(!r_ram_data_rd & r_ram_data_rd_1d) 
      ro_post_last<='d1;
   else 
      ro_post_last<='d0;
end

always @(posedge i_post_clk , posedge i_post_rst) 
begin   
   if(r_read_cnt == w_fifo_len_dout) 
   r_ram_addr_B<='d0;
    else if(r_ram_data_rd)
   r_ram_addr_B<=r_ram_addr_B+1;
    else  
    r_ram_addr_B<='d0;
end

//检测是否快满
always@(posedge i_per_clk,posedge i_per_rst) 
begin
    if(i_per_rst)
        ro_per_ready <= 'd0;
    else if(r_ram_addr_B==55)    //快满了  一帧数据50
        ro_per_ready <= 'd0;
    else
        ro_per_ready <= 'd1;
end

endmodule
// An highlighted block

module fifo_ram_tb(

    );


    reg clk,rst;
    reg clk_f,rst_f;
    
    always
    begin
        clk = 0;
        #10;
        clk = 1;
        #10;
    end
    
    
    initial begin
        rst = 1;
        #100@(posedge clk)rst <= 0;//同步释放
    end
    
    
    always
    begin
        clk_f = 0;
        #5;
        clk_f = 1;
        #5;
    end
    
    
    initial begin
        rst_f = 1;
        #100@(posedge clk_f)rst_f <= 0; //同步释放
    end


 
// Parameters

//Ports
 
  reg           [11:0]         r_per_data        ;
  reg                          r_per_last        ;
  reg                          r_per_valid       ;



fifo_ram  fifo_ram_inst (
  .i_per_clk                        (clk              ),
  .i_per_rst                        (rst              ),
  .i_per_data                       (r_per_data       ),
  .i_per_last                       (r_per_last       ),
  .i_per_valid                      (r_per_valid      ),
  .o_per_ready                      (                 ),

  .i_post_clk                       (clk_f            ),
  .i_post_rst                       (rst_f            ),
  .o_post_data                      (                 ),
  .o_post_last                      (                 ),
  .o_post_valid                     (                 ),
  .i_post_ready                     (1     ) 
);




initial
begin
    r_per_data  = 0;
    r_per_last  = 0;
    r_per_valid = 0;
    wait(!rst);
    forever begin
        repeat(10)@(posedge clk);//运行10个空周期
        per_send(10);
        repeat(10)@(posedge clk);
        per_send(20);
        repeat(10)@(posedge clk);
        per_send(30);
        repeat(10)@(posedge clk);
    end
end

reg   [11:0] cnt ;

task per_send(input [15:0] len);
begin:per_send_task
    integer i;
    r_per_data  <= 'd0;
    r_per_last  <= 'd0;
    r_per_valid <= 'd0;
    cnt         <= 'd0;
    @(posedge clk);
    for(i = 0;i < len;i = i + 1)
    begin
        r_per_data  <= cnt;                                 
        if(i == len - 1)r_per_last  <= 'd1;
        else r_per_last  <= 'd0;
        r_per_valid <= 'd1;
        cnt <= cnt + 1;
        @(posedge clk);
    end
    r_per_data  <= 'd0;
    r_per_last  <= 'd0;
    r_per_valid <= 'd0;
    cnt         <= 'd0;
    @(posedge clk);
end
endtask

 
endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值