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
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