Hey guys! I'm still working with FPGAs and I hit kind of an odd problem but I'm sure its very simple.
First off I'm using the Nexys 2 board and I'm trying to make a memory controller for the on board memory.
I'm getting these two, simple enough, errors:
ERROR:Xst:528 - Multi-source in Unit <sram_test> on signal <N0>; this signal is connected to multiple drivers.
ERROR:Xst:528 - Multi-source in Unit <sram_control> on signal <LB_sram>; this signal is connected to multiple drivers.
The strange part about this is for the first error, the signal N0 is never used in my program. I did a ctrl+f of the file and 'N0' isn't even in it. The second error at least references an signal I can find. The problem this time is that the signal is defined as an output and the only time it is used it is assigned the constant zero.
Before I post the code I'd like to say that I am still very terrible at Verilog and when I write Verilog I feel as clumsy as a drunk baby. But I doubt you would need to look though all of it.
Here is the program that generated the first error. It's purpose is just to test the memory controller that I wrote.
`timescale 1ns / 1ps
module sram_test(
input [2:0] btn, // Buttons used for output
input clk, reset,
input [7:0] sw, // Will be used for the data input and address to the memory
output [7:0] led, // Outputs for the read operation
// Outputs that are generated by the memory controller
output OE_sram, WE_sram, CE_sram, ADV_sram, LB_sram, UB_sram,
output [23:0] addr_sram,
inout [15:0] dio_sram
);
// Symbolic state defintions
localparam [1:0]
idle = 2'b00,
read = 2'b01,
write = 2'b10;
// Internal definions
reg [7:0] data_reg, data_next, data_out_reg, data_out_next;
reg [1:0] state, state_next;
reg mem, mem_next, rw, rw_next;
wire [2:0] db_btn;
wire [7:0] sram_output;
wire ready;
// Register transistion
always @(posedge clk)
begin
if (reset)
begin
data_reg <= 0;
state <= idle;
data_out_reg <= 0;
mem <= 0;
rw <= 0;
end
else
begin
data_reg <= data_next;
state <= state_next;
data_out_reg <= data_out_next;
mem <= mem_next;
rw <= rw_next;
end
end
// FSMD
always @*
begin
data_next = data_reg;
state_next = state;
data_out_next = data_out_reg;
mem_next = 1'b0;
case(state)
idle:
begin
if (db_btn[0]) // Load to data reg
begin
data_next = sw;
end
else if (db_btn[1]) // Write
begin
state_next = write;
end
else // Read
begin
state_next = read;
end
end
write:
begin
mem_next = 1'b1;
rw = 1'b0;
if (ready)
state_next = idle;
end
read:
begin
mem_next = 1'b1;
rw = 1'b1;
if (ready)
begin
state_next = idle;
data_out_next = sram_output;
end
end
endcase
end
assign led = data_out_reg;
sram_control sram1
( .addr_in(sw), .data_in(data_reg), .mem(mem), .rw(rw), .clk(clk),
.reset(reset), .ready(ready), .data_out_reg(sram_output), .addr_sram(addr_sram),
.dio_sram(dio_sram), .OE_sram(OE_sram), .WE_sram(WE_sram), .CE_sram(CE_sram),
.ADV_sram(ADV_sram), .LB_sram(LB_sram), .UB_sram(UB_sram) );
debounce unit0
( .clk(clk), .reset(reset), .sw(btn[0]), .db_tick(db_btn[0]) );
debounce unit1
( .clk(clk), .reset(reset), .sw(btn[1]), .db_tick(db_btn[1]) );
debounce unit2
( .clk(clk), .reset(reset), .sw(btn[2]), .db_tick(db_btn[2]) );
endmodule
The second one is a little more complicated. It is attempting to access a Micron M45W8MW16 8MBx16 RAM chip. I'm being very generous on the timing of this and I'm pretty sure there are some wasted cycles. This is my first attempt so I wasn't going for the highest speed.
`timescale 1ns / 1ps
module sram_control(
// Controller data inputs
input [23:0] addr_in,
input [15:0] data_in,
// Controller control inputs
input mem, rw, clk, reset,
// Controler control outputs
output ready,
// Controler data outputs
output [15:0] data_out, data_out_reg,
// SRAM data outputs (IE going to the sram)
output [23:0] addr_sram,
inout [15:0] dio_sram,
// SRAM control outputs
output OE_sram, WE_sram, CE_sram, ADV_sram, LB_sram, UB_sram
);
// Symbolic state definitions
localparam [3:0]
idle = 4'b0000,
read0 = 4'b0001,
read1 = 4'b0010,
read2 = 4'b0011,
read3 = 4'b0100,
write0 = 4'b0101,
write1 = 4'b0110,
write2 = 4'b0111,
write3 = 4'b1000,
write4 = 4'b1001,
write5 = 4'b1010;
// Internal defintions
reg [3:0] state, state_next;
reg [23:0] address_reg, address_next;
reg [15:0] data_to_sram, data_from_sram, data_to_sram_next, data_from_sram_next;
reg we_reg, we_next, oe_reg, oe_next, tri_reg, tri_next, ready_reg, ready_next;
// FSMD register and data transitions
always @(posedge clk)
begin
if (reset)
begin
state <= idle;
address_reg <= 0;
data_to_sram <= 0;
data_from_sram <= 0;
we_reg <= 1'b1;
oe_reg <= 1'b1;
tri_reg <= 1'b1;
ready_reg <= 1'b1;
end
else
begin
state <= state_next;
address_reg <= address_next;
data_to_sram <= data_to_sram_next;
data_from_sram <= data_from_sram_next;
we_reg <= we_next;
oe_reg <= oe_next;
tri_reg <= tri_next;
ready_reg <= ready_next;
end
end
// FSMD next-state logic
always @*
begin
state_next = state;
address_next = address_reg;
data_to_sram_next = data_to_sram;
data_from_sram_next = data_from_sram;
we_next = we_next;
oe_reg = oe_next;
tri_next = tri_reg;
ready_next = ready_reg;
case(state)
idle:
begin
if(mem)
begin
if(rw) // Read
begin
state_next = read0;
address_next = addr_in;
tri_next = 1'b1;
ready_next = 1'b0;
end
else // Write
begin
state_next = write0;
address_next = addr_in;
data_to_sram_next = data_in;
tri_next = 1'b1;
ready_next = 1'b0;
// More here possibly
end
end
else
begin
ready_next = 1'b1;
oe_next = 1'b1;
we_next = 1'b1;
end
end
read0: // Assert OE
begin
state_next = read1;
oe_next = 1'b0;
end
read1: // Wait 20ns
state_next = read2;
read2: // Wait 20ns
state_next = read3;
read3: // Read the data
begin
state_next = idle;
data_from_sram = dio_sram;
end
write0: // Assert WE and the tri-state buffer
begin
state_next = write1;
tri_next = 1'b0;
we_next = 1'b0;
end
write1: // Wait 20ns
state_next = write2;
write2: // Wait 20ns
state_next = write3;
write3: // Wait 20ns
state_next = write4;
write4: // Unassert WE and wait 20ns
begin
state_next = write5;
we_next = 1'b1;
end
write5: // Take the data off(unassert the tri-sate buffer)
begin
state_next = idle;
tri_next = 1'b1;
end
default: state_next = idle;
endcase
end
assign AVD_sram = 1'b0;
assign LB_sram = 1'b0;
assign UB_sram = 1'b0;
assign CE_sram = 1'b0;
assign data_out = dio_sram;
assign data_out_reg = data_from_sram;
assign dio_sram = (~tri_reg) ? data_to_sram : 16'bz;
endmodule
I hope that wasn't too irritating to read. I'm still not very sure how to write readable Verilog(if that exists).
Thanks!