Search code examples
moduleverilogfpgaxilinx

How to enable the instantiated modules in sequence in verilog


I have different modules instantiated in one single module. I want to execute them in sequence, I have enable and acknowledgement signals of all modules how can I do this?

Following is the code:

module memorycontroller(
    input  [7:0] A,
    input  [7:0] B,
    input  [1:0] adrress,
    input        clk,
    output [7:0] A_mem,
    output [7:0] B_mem
);
    reg          LMwrEnable, localmemEnable;
    integer      LMwrack,    localmemack;
    reg    [7:0] A1, B1;

    initial
    begin
      LMwrEnable     = 1;
      localmemEnable = 0;
    end

    memorywrite LMwr (
      .clk     ( clk        ), 
      .A       ( A          ), 
      .B       ( B          ), 
      .adr     ( adrress    ),
      .enable  ( LMwrEnable ),
      .ack     ( LMwrack    )
    );

    bram_tdp localmem (
      .a_clk   ( clk            ), 
      .a_wr    ( 1'b0           ), 
      .a_addr  ( adrress        ), 
      .a_din   ( A1             ), 
      .a_dout  ( A_mem          ), 
      .b_clk   ( clk            ), 
      .b_wr    ( 1'b0           ), 
      .b_addr  ( adrress+1'b1   ), 
      .b_din   ( B1             ), 
      .b_dout  ( B_mem          ),
      .enable  ( localmemEnable ),
      .ack     ( localmemack    )
    );

     always@(posedge clk)
     begin
       if(LMwrack)
         localmemEnable = 1;
     end


endmodule

In initial statement I've enabled only LMwr module in initial block and on its ack signal I have enabled localmem module in always block but this is giving me wrong result. Can you tell me how to execute different modules in sequence?

Following is the memorywrite module

module memorywrite(
    input clk,
    input [7:0] A,
    input [7:0] B,
    input [1:0] adr,
     input enable,
     output ack
    );
     wire [7:0] C,C1;

 bram_tdp localmem (
    .a_clk(clk), 
    .a_wr(1'b1), 
    .a_addr(adr), 
    .a_din(A), 
    .a_dout(C), 
    .b_clk(clk), 
    .b_wr(1'b1), 
    .b_addr(adr+1'b1), 
    .b_din(B), 
    .b_dout(C1),
     .enable(enable),
     .ack(ack)
    );

endmodule

This above code writes to the memory.

Following is the actual memory module which is being written by 2nd code stated above and read by 1st code stated above

module bram_tdp #(
    parameter DATA = 8,
    parameter ADDR = 2
) (
     input enable,
     output ack,
    // Port A
    input   wire                a_clk,
    input   wire                a_wr,
    input   wire    [ADDR-1:0]  a_addr,
    input   wire    [DATA-1:0]  a_din,
    output  reg     [DATA-1:0]  a_dout,

    // Port B
    input   wire                b_clk,
    input   wire                b_wr,
    input   wire    [ADDR-1:0]  b_addr,
    input   wire    [DATA-1:0]  b_din,
    output  reg     [DATA-1:0]  b_dout
);

// Shared memory
reg [DATA-1:0] mem [(2**ADDR)-1:0];

// Port A
always @(posedge a_clk) begin
if(enable) begin
    a_dout      <= mem[a_addr];
    if(a_wr) begin
        a_dout      <= a_din;
        mem[a_addr] <= a_din;
    end
    end
end

// Port B
always @(posedge b_clk) begin
if(enable) begin
    b_dout      <= mem[b_addr];
    if(b_wr) begin
        b_dout      <= b_din;
        mem[b_addr] <= b_din;
    end

    end
end
assign ack=1;
endmodule

Here is testbench:

module mmTesting;

    // Inputs
    reg [7:0] A;
    reg [7:0] B;
    reg [1:0] adrress;
    reg clk;

    // Outputs
    wire [7:0] A_mem;
    wire [7:0] B_mem;

    // Instantiate the Unit Under Test (UUT)
    memorycontroller uut (
        .A(A), 
        .B(B), 
        .adrress(adrress), 
        .clk(clk), 
        .A_mem(A_mem), 
        .B_mem(B_mem)
    );

    initial begin
        // Initialize Inputs
        A = 0;
        B = 0;
        adrress = 0;
        clk = 0;

        // Wait 100 ns for global reset to finish
        #100;
      A = 5;
        B = 5;
        adrress = 0;

      #100 A = 6;
        B = 2;
        adrress = 1;


        // Add stimulus here

    end
     always #5 clk=!clk; 
endmodule

Result should be same as what I am writing to the memory.


Solution

  • Just to clarify that Verilog is a hardware description and that both instantiations (not modules, as an uninstantiated module does not exist) can be executed and exist in parallel, unlike the C equivalent which would execute one then the other.

    If you have instance A and B, you just need a FSM (Finite State Machine) to enable A wait for its completion signal, then disabling A enable B, waiting for B to complete and repeat.

    NB: if the commented out code is not relevant to the question can it be removed, it is good practise to reduce your question to the minimum amount of code required to reproduce the problem.