Search code examples
verilogxilinxsynthesis

synthesize-xst in xillinx get a long time


I am beginner in verilog and xilinx, and I am writing a quad port ram in verilog,

I want to synthesize my code, but although my code is small, it takes a very long time for synthesize witch I force to stop it and I can not synthesize my code.

I don't know where is the problem and what should I do?here is my own code..

module Dram(CLKM,WEA,WEB,WEC,WED,ENA,ENB,ENC,END,DIA,DIB,DIC,DID,ADDRA,ADDRB,ADDRC,ADDRD,DOA,DOB,DOC,DOD);
input WEA,WEB,WEC,WED,ENA,ENB,ENC,END;
input [17:0]DIA,DIB,DIC,DID;
input [9:0]ADDRA,ADDRB,ADDRC,ADDRD;
input CLKM;
output reg [17:0] DOA,DOB,DOC,DOD;
reg state_reg,state_next;
reg [17:0]ram[1023:0];
always@(posedge CLKM)
begin
    state_reg=state_next;
end///edn for always
always@(negedge  CLKM)
begin
    case(state_reg)
        1'b0:
        begin
            if(ENA)
            begin
                if(WEA)
                    ram[ADDRA]<=DIA;
                DOA<=ram[ADDRA];
            end//////for enA
            if(ENB)
            begin
                if(WEB)
                    ram[ADDRB]<=DIB;
                DOB<=ram[ADDRB];
            end////for enB
            state_next=1'b1;
        end////for 1'b0
        1'b1:
        begin
            if(ENC)
            begin
                if(WEC)
                    ram[ADDRC]<=DIC;
                DOC<=ram[ADDRC];
            end
            if(END)
            begin
                if(WED==1'b1)
                    ram[ADDRD]<=DID;
                DOD<=ram[ADDRD];
            end
            state_next=1'b0;
        end///end for 1'b1
    endcase
end//end for always

endmodule

I thought it is a simple code and doesn't get very time, but now I can not synthesize my code? where is the problem? plz help me!!! thanks


Solution

  • The problem lies in how you access the ram array. You are doing that inside a combinational block. This makes XST to build your RAM using distributed RAM, not block RAM, and builds tons of multiplexers to cover all 1024 possible combinations for ADDRA/ADDRB/ADDRC/ADDRD signals. That is why you are experiencing long synthetizing times.

    Rethink your logic so that code like ram[ADDR] <= value or value <= ram[ADDR] is always inside a clock triggered always


    After your edited code: I then suggest to separate the quadport RAM logic from the RAM logic itself. You relay on a standard single port RAM module, and then using a FSM, makes it act as if it would have many ports, don't you? Your single port RAM, and the source of your headaches can be described as this:

    module spram (input wire clk,
      input wire en,
      input wire we,
      input wire [9:0] addr,
      input wire [17:0] din,
      output reg [17:0] dout
      );
    
      reg [17:0] ram[0:1023];
    
      always @(negedge clk) begin
        if (en) begin
          if (we) begin
            ram[addr] <= din;
          end
          dout <= ram[addr];
        end
      end
    endmodule
    

    Describing the memory this way will help XST to infere it as a block RAM device, as pointed by the advanced syntesis report:

    Synthesizing (advanced) Unit <spram>.
    INFO:Xst:3040 - The RAM <Mram_ram> will be implemented as a BLOCK RAM, absorbing the following register(s): <dout>
        -----------------------------------------------------------------------
        | ram_type           | Block                               |          |
        -----------------------------------------------------------------------
        | Port A                                                              |
        |     aspect ratio   | 1024-word x 18-bit                  |          |
        |     mode           | read-first                          |          |
        |     clkA           | connected to signal <clk>           | fall     |
        |     enA            | connected to signal <en>            | high     |
        |     weA            | connected to signal <we>            | high     |
        |     addrA          | connected to signal <addr>          |          |
        |     diA            | connected to signal <din>           |          |
        |     doA            | connected to signal <dout>          |          |
        -----------------------------------------------------------------------
        | optimization       | speed                               |          |
        -----------------------------------------------------------------------
    Unit <spram> synthesized (advanced).
    

    Then you can instantiate this RAM into your quadport design and multiplex signals depending on what state you are. Something like this:

    module qpram (input wire clk,
      input wire [3:0] en,
      input wire [3:0] we,
      input wire [9:0] addra,
      input wire [9:0] addrb,
      input wire [9:0] addrc,
      input wire [9:0] addrd,
      input wire [17:0] dina,
      input wire [17:0] dinb,
      input wire [17:0] dinc,
      input wire [17:0] dind,
      output reg [17:0] douta,
      output reg [17:0] doutb,
      output reg [17:0] doutc,
      output reg [17:0] doutd
      );
    
      reg [1:0] port = 2'b00; /* indicates which port is active */
      always @(negedge clk) begin
        port <= port + 1;
      end
    
      /* instantiate single port RAM */
      reg enable,write;
      reg [17:0] din;
      wire [17:0] dout;
      reg [9:0] addr;
      spram myram (clk,enable,write,addr,din,dout);
    
      /* multiplexers to assign right inputs to RAM
      depending on which port we are in */
      always @* begin
        case (port)
          2'b00 : begin
                    addr = addra;
                    write = we[0];
                    enable = en[0];
                    din = dina;
                  end
          2'b01 : begin
                    addr = addrb;
                    write = we[1];
                    enable = en[1];
                    din = dinb;
                  end
          2'b10 : begin
                    addr = addrc;
                    write = we[2];
                    enable = en[2];
                    din = dinc;
                  end
          2'b11 : begin
                    addr = addrd;
                    write = we[3];
                    enable = en[3];
                    din = dinc;
                  end
        endcase
      end
    
      /* data out is available at the end of each clock cycle */
      always @(negedge clk) begin
        case (port)
          2'b00 : douta <= dout;
          2'b01 : doutb <= dout;
          2'b10 : doutc <= dout;
          2'b11 : doutd <= dout;
        endcase
      end
    endmodule