[[FIFO to multiplier to RAM verilog code and testbnench]]

Verilog code and testbnench for FIFO to multiplier to RAM

Only the transmission of a single data is completed. Big data needs to be modified tb or basic connections.

FIFO.v

//synchronous fifo
module FIFO_syn #(
    parameter WIDTH = 16, // the fifo wide
    parameter DEPTH = 1024, // depth
    parameter ADDR_WIDTH = clogb2(DEPTH) // bit wide
 // parameter PROG_EMPTY = 100, // this what we set to empty
  // parameter PROG_FULL = 800 // this what we set to full
  )
  (
    input sys_clk,
    input sys_rst_n ,
    input wr_en,
    input rd_en,
    input [WIDTH-1: 0] din ,
    output reg full,
    output reg empty , /// 1 is real empty 0 is no empty
    output reg [WIDTH-1:0] dout
  );

  //================================================ ========================================//
  // define parameter and internal signals //
  //================================================ ======================================//
  reg [WIDTH-1 : 0] ram[DEPTH-1 : 0] ; // this we set a 15:0 total 1024 number ram
  reg [ADDR_WIDTH-1 : 0] wr_addr ; // this is write pointer
  reg [ADDR_WIDTH-1 : 0] rd_addr ; // this is read pointer
  reg [ADDR_WIDTH-1 : 0] fifo_cnt;

  //================================================ =========================================//
  // next is main code //
  //================================================ =========================================//

  // we set a function let me to count the number
  function integer clogb2; // remember integer has symbol reg has no symbol
    input[31:0]value;
    begin
      value=value-1;
      for(clogb2=0;value>0;clogb2=clogb2 + 1)
        value=value>>1;
    end
  endfunction
  // this you can see from the PPT 5-74


  //================================================ === next is used to read

  always@(posedge sys_clk or negedge sys_rst_n)
  begin
    if(sys_rst_n == 0)
      rd_addr <= {<!-- -->ADDR_WIDTH{<!-- -->1'b0}};
    else if(rd_en & amp; & amp; !empty)
    begin
      rd_addr <= rd_addr + 1'd1;
      dout <= ram[rd_addr];
    end
    else
    begin
      rd_addr <= rd_addr;
      dout <= dout;
    end
  end




  //================================================ === next is used to write
  always@(posedge sys_clk or negedge sys_rst_n)
  begin
    if(sys_rst_n == 0)
    begin
      wr_addr <= {<!-- -->ADDR_WIDTH{<!-- -->1'b0}} ; // this let pointer to zero
    end
    else if( wr_en & amp; & amp; !full )
    begin // no full and wr_en and whether to write prog_full there
      wr_addr <= wr_addr + 1'b1;
      ram[wr_addr] <= din;
    end
    else
      wr_addr <= wr_addr;
  end





  //================================================ ============== next is used to set fifo_cnt
  always@(posedge sys_clk or negedge sys_rst_n )
  begin
    if(sys_rst_n == 0)
    begin
      fifo_cnt <= {<!-- -->ADDR_WIDTH{<!-- -->1'b0}};
    end
    else if(wr_en & amp; & amp; !full & amp; & amp; !rd_en)
    begin
      fifo_cnt <= fifo_cnt + 1'b1;
    end
    else if(rd_en & amp; & amp; !empty & amp; & amp; !wr_en)
    begin
      fifo_cnt <= fifo_cnt - 1'b1;
    end
    else
      fifo_cnt <= fifo_cnt;
  end


  //================================================ ========== next is empty
  // we set counter so when the count is zero empty
  always@(posedge sys_clk or negedge sys_rst_n)
  begin
    if(sys_rst_n == 0)
    begin
      empty <= 1'b1; // begin we set empty to high
    end
    // there is two possibilties first no write fifo_cnt is all zero
    //second is no write it will be change to zero is just a will empty signal
    else
      empty <= (!wr_en & amp; & amp; (fifo_cnt[ADDR_WIDTH-1:1] == 'b0)) & amp; & amp;((fifo_cnt[0] == 1'b0) || rd_en );
  end



  //================================================ ============ next is full

  always@(posedge sys_clk or negedge sys_rst_n)
  begin
    if(sys_rst_n == 0 )
      full <= 1'b1;//reset:1
    else
      full <= (!rd_en & amp; & amp; (fifo_cnt[ADDR_WIDTH-1:1]=={<!-- -->(ADDR_WIDTH-1){<!-- -->1'b1}} )) & amp; & amp; ((fifo_cnt[0] == 1'b1) || wr_en);
  end

endmodule

multiplier.v

module uumultiplier #(
    parameter NUMBER1 = 8 ,
    parameter NUMBER2 = 8
  )(
    input [NUMBER1-1 : 0] input1 ,
    input [NUMBER2-1 : 0] input2 ,
    inputclk,
    input rst_n ,
    input begin_en,
    output reg finish_en ,
    output reg [NUMBER1 + NUMBER2 : 0] out
  );


  //================================================ ======================================\
  // define parameter and internal signal \
  //================================================ ======================================\
  reg [1:0] LCD = 2'b10;
  reg [1:0] LCD1;

  //================================================ ==========================================\
  // next is main code \
  //================================================ ===========================================\

always@(posedge clk or negedge rst_n) begin

 if(rst_n == 0)
    begin
      out <= 0 ;
    end

    else
       LCD1 <= LCD ;
    end

  always@(posedge clk or negedge rst_n)
  begin
    if(rst_n == 0)
    begin
      out <= 0 ;
    end

    else if(begin_en & amp; & amp; finish_en )
    begin

      out <= input1 * input2 ;
      LCD <= {<!-- -->LCD[0],LCD[1]};
    end
    else
      out <= out ;
  end

  always@(posedge clk or negedge rst_n)
  begin
    if(rst_n == 0)
    begin
      finish_en <= 1'b1;
    end
    else if(LCD == LCD1)
    begin
      finish_en <= 1'b1;
    end
    else
      finish_en <= 1'b0;
  end


endmodule

RAM.v

//DUal ended RAM
module RAM #(
    parameter WIDTH = 8 ,
    parameter DEPTH = 16 ,
    parameter ADD_WIDTH = clogb2(DEPTH)
)(
    input wr_clk,
    input rd_clk,
    input wr_en,
    input rd_en,
    input [WIDTH-1 : 0 ] din ,
    input [ADD_WIDTH-1 : 0] wr_address ,
    output reg [WIDTH-1 : 0 ] dout ,
    input [ADD_WIDTH-1 : 0] rd_address
);


//================================================ ==================================\
// define parameter and internal signal \
//================================================ ==================================\

reg [WIDTH - 1 : 0 ] ram [DEPTH - 1 : 0] ;





//================================================ ==================================\
// next is main code \
//================================================ ==================================\


function integer clogb2;
input [31:0] value;
begin
    value = value - 1;
    for(clogb2 = 0; value > 0; clogb2 = clogb2 + 1)
    value = value >> 1 ;
end
endfunction


// write
always@(posedge wr_clk)
begin
    if(wr_en) begin
        ram[wr_address] <= din;
    end
end

//read
always@(posedge rd_clk)
begin
    if(rd_en) begin
        dout <= ram[rd_address];
    end
end
endmodule

top.v

module dig_top #(
  parameter FIFO_WIDTH = 8 ,
  parameter FIFO_DEPTH = 8 ,
  parameter FIFO_ADDR_WIDTH = clogb2(FIFO_DEPTH) ,
  parameter NUMBER1 = 8 ,
  parameter NUMBER2 = 2,
  parameter RAM_WIDTH = NUMBER1 + NUMBER2 + 1 ,
  parameter RAM_DEPTH = 8 ,
  parameter RAM_ADDR_WIDTH = clogb2(RAM_DEPTH)
)(
  input sys_clk,
  input sys_rst_n ,
  input wr_en,
  input rd_en,
  input [FIFO_WIDTH-1 : 0] din ,
  input RAM_rd_en ,
  input [RAM_ADDR_WIDTH-1 : 0] wr_address ,
  input [RAM_ADDR_WIDTH-1 : 0] rd_address ,
  output wire [RAM_WIDTH-1 : 0] dout
);


//================================================ =============================\
// define parameter and internal signals \
//================================================ =============================\

wire full;
wire empty;
wire [FIFO_WIDTH-1 : 0] dout1 ;
wire finish_en;
wire [RAM_WIDTH-1 : 0 ] dout2 ;





//================================================ ===============================\
// next is main code \
//================================================ =================================\
function integer clogb2;
    input [31:0] value;
    begin
      value = value - 1;
      for( clogb2 = 0 ; value > 0 ; clogb2 = clogb2 + 1)
        value = value >>1;
    end
  endfunction



FIFO_syn # (
    .WIDTH(FIFO_WIDTH),
    .DEPTH(FIFO_DEPTH),
    .ADDR_WIDTH(FIFO_ADDR_WIDTH)
  )
  FIFO_syn_inst (
    .sys_clk(sys_clk),
    .sys_rst_n(sys_rst_n),
    .wr_en(wr_en),
    .rd_en(rd_en),
    .din(din),
    .full(full),
    .empty(empty),
    .dout(dout1)
  );

  uumultiplier # (
    .NUMBER1(NUMBER1),
    .NUMBER2(2'b10)
  )
  uumultiplier_inst (
    .input1(dout1),
    .input2(2'b10),
    .clk(sys_clk),
    .rst_n(sys_rst_n),
    .begin_en(rd_en),
    .finish_en(finish_en),
    .out(dout2)
  );


  RAM # (
    .WIDTH(RAM_WIDTH),
    .DEPTH(RAM_DEPTH),
    .ADD_WIDTH(RAM_ADDR_WIDTH)
  )
  RAM_inst (
    .wr_clk(sys_clk),
    .rd_clk(sys_clk),
    .wr_en(finish_en),
    .rd_en(RAM_rd_en),
    .din(dout2),
    .wr_address(wr_address),
    .dout(dout),
    .rd_address(rd_address)
  );


endmodule

top_tb.v

`timescale 1ns/1ns
module top_tb #(
  parameter FIFO_WIDTH = 4 ,
  parameter FIFO_DEPTH = 8 ,
  parameter FIFO_ADDR_WIDTH = 3 ,
  parameter NUMBER1 = 4,
  parameter NUMBER2 = 2,
  parameter RAM_WIDTH = 7 ,
  parameter RAM_DEPTH = 8 ,
  parameter RAM_ADDR_WIDTH = 3
);
reg sys_clk;
reg sys_rst_n;
reg wr_en;
reg rd_en;
reg [FIFO_WIDTH-1 : 0] din ;
reg RAM_rd_en;
reg [RAM_ADDR_WIDTH-1 : 0] wr_address ;
reg [RAM_ADDR_WIDTH-1 : 0] rd_address;
wire [RAM_WIDTH-1 : 0] dout ;
reg [11:0] cnt;


dig_top # (
    .FIFO_WIDTH(FIFO_WIDTH),
    .FIFO_DEPTH(FIFO_DEPTH),
    .FIFO_ADDR_WIDTH(FIFO_ADDR_WIDTH),
    .NUMBER1(NUMBER1),
    .NUMBER2(NUMBER2),
    .RAM_WIDTH(RAM_WIDTH),
    .RAM_DEPTH(RAM_DEPTH),
    .RAM_ADDR_WIDTH(RAM_ADDR_WIDTH)
  )
  dig_top_inst (
    .sys_clk(sys_clk),
    .sys_rst_n(sys_rst_n),
    .wr_en(wr_en),
    .rd_en(rd_en),
    .din(din),
    .RAM_rd_en(RAM_rd_en),
    .wr_address(wr_address),
    .rd_address(rd_address),
    .dout(dout)
  );

  always #5 sys_clk = ~sys_clk;

  initial begin
    sys_clk = 1;
    sys_rst_n = 0;
    #100
    sys_rst_n = 1;
  end
  always #10 sys_clk = ~sys_clk;
  initial begin
    sys_clk = 0;
    sys_rst_n = 1;
    wr_en = 0;
    rd_en = 0;
    wr_address = 1;
    rd_address = 1;





    #10

    sys_rst_n = 0;

    #10
    sys_rst_n = 1;

    #10
    // next is write
    wr_en = 1;
    rd_en = 1;

    din = 2;
    
// RAM read
    RAM_rd_en = 1;
  
  end

endmodule