FPGARelated.com
Forums

"Multi-source in Unit" Verilog synthesis woes

Started by NRClark April 14, 2008
Hi everybody,

I'm working on a hobbyist board I'm designing to do some audio DSP.
I'm a little new to Verilog,
although not to programming in general. So far the FPGA design work
has been going smoothly
enough, but I'm having some trouble with synthesizing the code I wrote
for my DAC. I tried to avoid
all of the 'common' mistakes and design for synthesizability, but
there's some I must have missed.

My design simulates just fine, but when I go to synthesize it I get
these weird "Multi-source" errors:

ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal
<shift_counter<4>>
ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal
<shift_counter<2>>
ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal
<shift_counter<1>>
ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal
<Msub__COND_2_Madd>
ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal
<Mcount_shift_counter>.

I can't find the bug in my design, which means it must be some bug in
my own understanding. :)

Any words of insight? My Verilog code follows.

Thanks,
Nick

//------------------------------------
code----------------------------------------
module dac_cs4345(CLK,		RST_N,	SCLK,
						LRCLK,	L_DATA,	R_DATA,
						DATAOUT);

//	In this design, CLK = 49.152MHz, MCLK = 24.576MHz,
//	SCLK = 6.144MHz, LRCLK = 96KHz. They are all in-phase
//	each other, with the various clocks being generated from
// a 49.152MHz crystal and another Veriog module containing
// counters.

// Module port declarations

	input CLK,	RST_N;
	input SCLK,	LRCLK;
	input [23:0] L_DATA, R_DATA;

	output reg DATAOUT;

// Internal declarations

	reg r1, r2;
	wire SCLK_DELAYED;

// Counter used as an index to access data serially.
	reg [4:0] shift_counter;

// L_Data and R_Data are both registered to protect against
// spurious transitions during conversion.
	reg [23:0] L_DATA_STORAGE;
	reg [23:0] R_DATA_STORAGE;

//	Begin Program

// Since our data is set up on the LRCLK edge, we have to allow
// some delay before accessing it. Since SCLK is the clock used
// pull data, a slightly delayed SCLK will be generated and used.
// SCLK_DELAYED arrives one CLK period after SCLK.

	always @(posedge CLK) begin
		r2 <= r1;
		r1 <= SCLK;
	end
	assign SCLK_DELAYED = r2;

// Both the L and R data are assumed to arrive at this module
// at the same time, and to be available at the rising
// edge of the provided LRCLK. Since LRCLK is the output
// waveform used for synching data, this is a valid assumption.
// L_data and R_data _must_ be set up some time before the
//	positive edge of LRCLK.

	always @(posedge LRCLK) begin
		L_DATA_STORAGE <= L_DATA;
		R_DATA_STORAGE <= R_DATA;
		shift_counter <= 31; // Reset count-down counter
	end

	always @(negedge LRCLK)
		shift_counter <= 31; // Reset count-down counter

// Output data is assigned here. DATAOUT is assigned the value of
// 0 if our counter has gone past the data's LSB. The DAC's
// left-channel data is supplied when LRCLK is high, and its
// right-channel data is spplied when LRCLK is low.

	always @(posedge SCLK_DELAYED) begin
		if(shift_counter < 8)
			DATAOUT = 0;
		else if(LRCLK == 1)
			DATAOUT = L_DATA_STORAGE[shift_counter-8];
		else
			DATAOUT = R_DATA_STORAGE[shift_counter-8];
	end

// The timing of this is such that shift_counter counts down
//	from 32 to 0 twice in each LRCLK - once per 'side'. This is
//	decremented after the output has already been assigned a value.
// shift_counter could also be decremented on the falling edge of
// SCLK_DELAYED without changing the result.

	always @(negedge SCLK) begin
		shift_counter <= shift_counter-1;
	end

	endmodule
"NRClark" <nicholas.clark@gmail.com> wrote in message
news:5b377f74-9395-46de-b771-dccba3d994d1@k1g2000prb.googlegroups.com...
> Hi everybody, > > I'm working on a hobbyist board I'm designing to do some audio DSP. > I'm a little new to Verilog, > although not to programming in general. So far the FPGA design work > has been going smoothly > enough, but I'm having some trouble with synthesizing the code I wrote > for my DAC. I tried to avoid > all of the 'common' mistakes and design for synthesizability, but > there's some I must have missed. > > My design simulates just fine, but when I go to synthesize it I get > these weird "Multi-source" errors: > > ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal > <shift_counter<4>> > ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal > <shift_counter<2>> > ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal > <shift_counter<1>> > ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal > <Msub__COND_2_Madd> > ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal > <Mcount_shift_counter>. > > I can't find the bug in my design, which means it must be some bug in > my own understanding. :) > > Any words of insight? My Verilog code follows. > > Thanks, > Nick > > //------------------------------------ > code---------------------------------------- > module dac_cs4345(CLK, RST_N, SCLK, > LRCLK, L_DATA, R_DATA, > DATAOUT); > > // In this design, CLK = 49.152MHz, MCLK = 24.576MHz, > // SCLK = 6.144MHz, LRCLK = 96KHz. They are all in-phase > // each other, with the various clocks being generated from > // a 49.152MHz crystal and another Veriog module containing > // counters. > > // Module port declarations > > input CLK, RST_N; > input SCLK, LRCLK; > input [23:0] L_DATA, R_DATA; > > output reg DATAOUT; > > // Internal declarations > > reg r1, r2; > wire SCLK_DELAYED; > > // Counter used as an index to access data serially. > reg [4:0] shift_counter; > > // L_Data and R_Data are both registered to protect against > // spurious transitions during conversion. > reg [23:0] L_DATA_STORAGE; > reg [23:0] R_DATA_STORAGE; > > // Begin Program > > // Since our data is set up on the LRCLK edge, we have to allow > // some delay before accessing it. Since SCLK is the clock used > // pull data, a slightly delayed SCLK will be generated and used. > // SCLK_DELAYED arrives one CLK period after SCLK. > > always @(posedge CLK) begin > r2 <= r1; > r1 <= SCLK; > end > assign SCLK_DELAYED = r2; > > // Both the L and R data are assumed to arrive at this module > // at the same time, and to be available at the rising > // edge of the provided LRCLK. Since LRCLK is the output > // waveform used for synching data, this is a valid assumption. > // L_data and R_data _must_ be set up some time before the > // positive edge of LRCLK. > > always @(posedge LRCLK) begin > L_DATA_STORAGE <= L_DATA; > R_DATA_STORAGE <= R_DATA; > shift_counter <= 31; // Reset count-down counter > end > > always @(negedge LRCLK) > shift_counter <= 31; // Reset count-down counter > > // Output data is assigned here. DATAOUT is assigned the value of > // 0 if our counter has gone past the data's LSB. The DAC's > // left-channel data is supplied when LRCLK is high, and its > // right-channel data is spplied when LRCLK is low. > > always @(posedge SCLK_DELAYED) begin > if(shift_counter < 8) > DATAOUT = 0; > else if(LRCLK == 1) > DATAOUT = L_DATA_STORAGE[shift_counter-8]; > else > DATAOUT = R_DATA_STORAGE[shift_counter-8]; > end > > // The timing of this is such that shift_counter counts down > // from 32 to 0 twice in each LRCLK - once per 'side'. This is > // decremented after the output has already been assigned a value. > // shift_counter could also be decremented on the falling edge of > // SCLK_DELAYED without changing the result. > > always @(negedge SCLK) begin > shift_counter <= shift_counter-1; > end > > endmodule
You adjust shift_counter in multiple processes (always @), which won't do. You should only have 1 clocked process modifying shift_counter. With all clocks being synchronously divided versions of CLK = 49.152MHz, you should substitute the other clocks by "enable"/edge detect signals clocked on CLK. The low frequency clocks can still be made available/imported from the external world. Regards, Alvin.
On Apr 14, 4:55 pm, "Alvin Andries"
<Alvin_Andries.no_s...@no.spam.versateladsl.be> wrote:
> "NRClark" <nicholas.cl...@gmail.com> wrote in message > > news:5b377f74-9395-46de-b771-dccba3d994d1@k1g2000prb.googlegroups.com... > > > > > Hi everybody, > > > I'm working on a hobbyist board I'm designing to do some audio DSP. > > I'm a little new to Verilog, > > although not to programming in general. So far the FPGA design work > > has been going smoothly > > enough, but I'm having some trouble with synthesizing the code I wrote > > for my DAC. I tried to avoid > > all of the 'common' mistakes and design for synthesizability, but > > there's some I must have missed. > > > My design simulates just fine, but when I go to synthesize it I get > > these weird "Multi-source" errors: > > > ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal > > <shift_counter<4>> > > ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal > > <shift_counter<2>> > > ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal > > <shift_counter<1>> > > ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal > > <Msub__COND_2_Madd> > > ERROR:Xst:528 - Multi-source in Unit <dac_cs4345> on signal > > <Mcount_shift_counter>. > > > I can't find the bug in my design, which means it must be some bug in > > my own understanding. :) > > > Any words of insight? My Verilog code follows. > > > Thanks, > > Nick > > > //------------------------------------ > > code---------------------------------------- > > module dac_cs4345(CLK, RST_N, SCLK, > > LRCLK, L_DATA, R_DATA, > > DATAOUT); > > > // In this design, CLK = 49.152MHz, MCLK = 24.576MHz, > > // SCLK = 6.144MHz, LRCLK = 96KHz. They are all in-phase > > // each other, with the various clocks being generated from > > // a 49.152MHz crystal and another Veriog module containing > > // counters. > > > // Module port declarations > > > input CLK, RST_N; > > input SCLK, LRCLK; > > input [23:0] L_DATA, R_DATA; > > > output reg DATAOUT; > > > // Internal declarations > > > reg r1, r2; > > wire SCLK_DELAYED; > > > // Counter used as an index to access data serially. > > reg [4:0] shift_counter; > > > // L_Data and R_Data are both registered to protect against > > // spurious transitions during conversion. > > reg [23:0] L_DATA_STORAGE; > > reg [23:0] R_DATA_STORAGE; > > > // Begin Program > > > // Since our data is set up on the LRCLK edge, we have to allow > > // some delay before accessing it. Since SCLK is the clock used > > // pull data, a slightly delayed SCLK will be generated and used. > > // SCLK_DELAYED arrives one CLK period after SCLK. > > > always @(posedge CLK) begin > > r2 <= r1; > > r1 <= SCLK; > > end > > assign SCLK_DELAYED = r2; > > > // Both the L and R data are assumed to arrive at this module > > // at the same time, and to be available at the rising > > // edge of the provided LRCLK. Since LRCLK is the output > > // waveform used for synching data, this is a valid assumption. > > // L_data and R_data _must_ be set up some time before the > > // positive edge of LRCLK. > > > always @(posedge LRCLK) begin > > L_DATA_STORAGE <= L_DATA; > > R_DATA_STORAGE <= R_DATA; > > shift_counter <= 31; // Reset count-down counter > > end > > > always @(negedge LRCLK) > > shift_counter <= 31; // Reset count-down counter > > > // Output data is assigned here. DATAOUT is assigned the value of > > // 0 if our counter has gone past the data's LSB. The DAC's > > // left-channel data is supplied when LRCLK is high, and its > > // right-channel data is spplied when LRCLK is low. > > > always @(posedge SCLK_DELAYED) begin > > if(shift_counter < 8) > > DATAOUT = 0; > > else if(LRCLK == 1) > > DATAOUT = L_DATA_STORAGE[shift_counter-8]; > > else > > DATAOUT = R_DATA_STORAGE[shift_counter-8]; > > end > > > // The timing of this is such that shift_counter counts down > > // from 32 to 0 twice in each LRCLK - once per 'side'. This is > > // decremented after the output has already been assigned a value. > > // shift_counter could also be decremented on the falling edge of > > // SCLK_DELAYED without changing the result. > > > always @(negedge SCLK) begin > > shift_counter <= shift_counter-1; > > end > > > endmodule > > You adjust shift_counter in multiple processes (always @), which won't do. > You should only have 1 clocked process modifying shift_counter. > With all clocks being synchronously divided versions of CLK = 49.152MHz, you > should substitute the other clocks by "enable"/edge detect signals clocked > on CLK. The low frequency clocks can still be made available/imported from > the external world. > > Regards, > Alvin.
Also in XST every clocked register needs to fit a flip-flop template. You can't have posedge and negedge of the same clock for example, even if you place the code in the same always block. In Xilinx parts dual clocked flip-flops (DDR flops) only exist in the I/O blocks and must be instantiated, not inferred. The standard template for an asynchronous set/reset flip-flop looks like: always @ (negedge SCLK or posedge LRCLK) if (LRCLK) // active high async reset on LRCLK begin shift_counter <= 31; // Reset count-down counter end else // negedge SCLK begin shift_counter <= shift_counter-1; end Regards, Gabor