Huh, ok. I'm using the base code in the RS232 debug directory - which I guess instantiates a BrianHG_DDR3_CONTROLLER_v16_top module, which in turn wants the FIFO.
Am I jumping ahead too far, here ?
[ah, ok, saw the edit. I can change things around a bit]
// *************************************************************************
// Output the CAS address on the DDR3 A bus.
// *************************************************************************
task SET_cas();
begin
OUT_A[9:0] <= S3_CAS[9:0] ; // Column address at the beginning of a sequential burst
if (DDR3_WIDTH_CAS==10) OUT_A[11] <= 1'b0 ; // Default 0 for additional column address.
else OUT_A[11] <= S3_CAS[10] ; // Assign the additional MSB Column address used in 4 bit DDR3 devices.
OUT_A[10] <= 1'b0 ; // Disable AUTO-PRECHARGE. We keep the banks open and precharge manually only when needed.
OUT_A[12] <= 1'b1 ; // Set burst length to BL8.
if (DDR3_WIDTH_ROW > 13)
OUT_A[DDR3_WIDTH_ROW-1:13] <= 0 ;
end
endtask
So the Gowin compiler doesn't like the code here when DDR_WIDTH_ROW = 13
The last line has the assumption that DDR_WIDTH_ROW > 13 I think. I've changed it to:Code: [Select]// *************************************************************************
// Output the CAS address on the DDR3 A bus.
// *************************************************************************
task SET_cas();
begin
OUT_A[9:0] <= S3_CAS[9:0] ; // Column address at the beginning of a sequential burst
if (DDR3_WIDTH_CAS==10) OUT_A[11] <= 1'b0 ; // Default 0 for additional column address.
else OUT_A[11] <= S3_CAS[10] ; // Assign the additional MSB Column address used in 4 bit DDR3 devices.
OUT_A[10] <= 1'b0 ; // Disable AUTO-PRECHARGE. We keep the banks open and precharge manually only when needed.
OUT_A[12] <= 1'b1 ; // Set burst length to BL8.
if (DDR3_WIDTH_ROW > 13)
OUT_A[DDR3_WIDTH_ROW-1:13] <= 0 ;
end
endtask
begin : Gowin_DQ_Strobes
wire gowin_dqs_out; // Internal: ODDR->IOBUF
wire gowin_dqs_in; // Internal: IOBUF->IDDR
wire gowin_dqs_tx; // Internal: OE on input to ODDR
ODDR gowin_dqs_oddr_inst
(
.Q0(gowin_dqs_out), // ODDR -> LVDS
.Q1(gowin_dqs_tx), // 1'b0 => output
.D0(1'b0), // Input data [SDR]
.D1(1'b1), // Input data [SDR]
.TX(~OE_DQS[x]), // Input 'output enable' 0=output
.CLK(DDR_CLK) // DDR clock
);
IDDR gowin_dqs_iddr_inst
(
.Q0(RDQS_pl[x]), // SDR to app #0
.Q1(RDQS_ph[x]), // SDR to app #1
.D(gowin_dqs_in), // DDR input signal
.CLK(DDR_CLK_RDQ) // read clock
);
TLVDS_IOBUF gowin_dqs_lvds_iobuf_inst
(
.O(gowin_dqs_in), // LVDS -> IDDR
.IO(DDR3_DQS_p[x]), // +ve LVDS pad
.IOB(DDR3_DQS_n[x]), // -ve LVDS pad
.I(gowin_dqs_out), // ODDR -> LVDS
.OEN(gowin_dqs_tx) // input when 1'b1
);
assign RDQS_nl[x] = ~RDQS_pl[x];
assign RDQS_nh[x] = ~RDQS_ph[x];
end
'different control net'? They do not specify which or what control net they are talking about?
Before we go haywire, let's see if there are different bidir IO buffers available.
Also, what options exist.
Also, if the DQ IO passes which does use 2 different clocks, then for the DQS, you can try the manual, or usually called emulated differential approach which I had to use for the older Cyclone devices.
Basically 2 single ended buffers in parallel, where the second IO output has the high and low 2'b01 inverted to 2'b10.
Try removing the IO buffers, just wiring the DDRs to the IO pin.
Maybe requesting the IO buffer primitive prevents the use of adjacent logic cells which may be clocked on a different net.
for (x=0; x<DQ_WIDTH; x = x + 1)
begin : gowin_DQ_bus
wire gowin_dq_tx_out;
ODDR gowin_dq_oddr_inst
(
.Q0(DDR3_DQ[x]), // ODDR -> IOBUF
.Q1(gowin_dq_tx_out), // OE -> IOBUF, 1'b0 => output
.D0(PIN_WDATA_PIPE_h[0][x]), // Input data [SDR]
.D1(PIN_WDATA_PIPE_l[0][x]), // Input data [SDR]
.TX(~PIN_OE_WDQ_wide[x]), // Input 'output enable' 1'b0=out
.CLK(DDR_CLK_WDQ) // write clock
);
IDDR gowin_dq_iddr_inst
(
.Q0(RDQ_l[x]), // SDR to app #0
.Q1(RDQ_h[x]), // SDR to app #1
.D(DDR3_DQ[x]), // DDR input signal
.CLK(DDR_CLK_RDQ) // read clock
);
end
Try removing the IO buffers, just wiring the DDRs to the IO pin.
Maybe requesting the IO buffer primitive prevents the use of adjacent logic cells which may be clocked on a different net.
Ok, so for DQ, removing the IOBUF does in fact make it pass compilation. The code now looks like:Code: [Select]for (x=0; x<DQ_WIDTH; x = x + 1)
begin : gowin_DQ_bus
wire gowin_dq_tx_out;
ODDR gowin_dq_oddr_inst
(
.Q0(DDR3_DQ[x]), // ODDR -> IOBUF
.Q1(gowin_dq_tx_out), // OE -> IOBUF, 1'b0 => output
.D0(PIN_WDATA_PIPE_h[0][x]), // Input data [SDR]
.D1(PIN_WDATA_PIPE_l[0][x]), // Input data [SDR]
.TX(~PIN_OE_WDQ_wide[x]), // Input 'output enable' 1'b0=out
.CLK(DDR_CLK_WDQ) // write clock
);
IDDR gowin_dq_iddr_inst
(
.Q0(RDQ_l[x]), // SDR to app #0
.Q1(RDQ_h[x]), // SDR to app #1
.D(DDR3_DQ[x]), // DDR input signal
.CLK(DDR_CLK_RDQ) // read clock
);
end
I'm not sure if this will work in reality, or whether it'll change the timing significantly (though I think the timing delays were in the DDR stages rather than the IOBUF stage).
Maybe I'm being dense, but I can't off-hand see how the LVDS can be implemented for the DQS signals without using an LVDS_IOBUF, I ought to go read that other code you mentioned to see how you did it ... Perhaps you're "faking" the LVDS part ? I guess I'll see.
for (x=0; x<DDR3_NUM_CK; x = x + 1)
begin : DDR_Clocks
wire gowin_clock;
wire gowin_ck_oe;
ODDR gowin_ck_ddr_inst_p
(
.Q0(DDR3_CK_p[x]), // Send +ve clock to this pin
.Q1(gowin_ck_oe), // Not used but save a warning
.D0(1'b0), // clock goes low to start
.D1(1'b1), // clock goes high in 2nd phase
.TX(1'b0), // TX=0 -> Output pin
.CLK(DDR_CLK) // DDR clock
);
assign DDR3_CK_n[x] = ~DDR3_CK_p[x];
end
for (x=0; x<DDR3_NUM_CK; x = x + 1)
begin : DDR_Clocks
wire gowin_clock;
wire gowin_ck_oe_p;
wire gowin_ck_oe_n;
ODDR gowin_ck_ddr_inst_p
(
.Q0(DDR3_CK_p[x]), // Send +ve clock to this pin
.Q1(gowin_ck_oe_p), // Not used but save a warning
.D0(1'b0), // clock goes low to start
.D1(1'b1), // clock goes high in 2nd phase
.TX(1'b0), // TX=0 -> Output pin
.CLK(DDR_CLK) // DDR clock
);
ODDR gowin_ck_ddr_inst_n
(
.Q0(DDR3_CK_n[x]), // Send -ve clock to this pin
.Q1(gowin_ck_oe_n), // Not used but save a warning
.D0(1'b1), // clock goes high to start
.D1(1'b0), // clock goes low in 2nd phase
.TX(1'b0), // TX=0 -> Output pin
.CLK(DDR_CLK) // DDR clock
);
end
Code: [Select]assign DDR3_CK_n[x] = ~DDR3_CK_p[x];
You are going to have 1 logic cell making the CK_P and driving that pin. Then, an un-clocked inverter gate making the CK_N. This will not do. There will be a delay from the P output to the N output.
wire gowin_dq_in;
wire gowin_dq_out;
wire gowin_dq_oe;
ODDR gowin_dq_oddr_inst
(
.Q0(gowin_dq_out), // 2x SDR -> DDR
.Q1(gowin_dq_oe), // in-phase output enable
.D0(PIN_WDATA_PIPE_h[0][x]), // Input data [SDR]
.D1(PIN_WDATA_PIPE_l[0][x]), // Input data [SDR]
.TX(PIN_OE_WDQ_wide[x]), // Input 'output enable'
.CLK(DDR_CLK_WDQ) // write clock
);
IOBUF gowin_dq_iobuf_inst
(
.O(gowin_dq_in), // IOBUF -> IDDR (unused)
.IO(DDR3_DQ[x]), // DQ pad
.I(gowin_dq_out), // ODDR -> IOBUF
.OEN(~gowin_dq_oe) // input when 1'b1
);
IDDR gowin_dq_iddr_inst
(
.Q0(RDQ_l[x]), // SDR to app #0
.Q1(RDQ_h[x]), // SDR to app #1
.D(DDR3_DQ[x]), // DDR input signal
.CLK(DDR_CLK_RDQ) // read clock
);
There is also asking Gowin.
I do not know about Gowin, but Altera does offer us visual diagrams in the data sheet showing us what type of wiring is available to each IO pin on the FPGA fabric. It shows us the allowable connections. Do you have such an illustration for Gowin. Maybe it can offer a hint...
It would be really frustrating if they only allow if from 1 PLL as we have a separate PLL for the write data.
Try adding a second IBUF from pin net, then tie that to the IDDR.
gowin_dq_in;
wire gowin_dq_out;
wire gowin_dq_oe;
wire gowin_ibuf_in;
ODDR gowin_dq_oddr_inst
(
.Q0(gowin_dq_out), // 2x SDR -> DDR
.Q1(gowin_dq_oe), // in-phase output enable
.D0(PIN_WDATA_PIPE_h[0][x]), // Input data [SDR]
.D1(PIN_WDATA_PIPE_l[0][x]), // Input data [SDR]
.TX(PIN_OE_WDQ_wide[x]), // Input 'output enable'
.CLK(DDR_CLK_WDQ) // write clock
);
IOBUF gowin_dq_iobuf_inst
(
.O(gowin_dq_in), // IOBUF -> IDDR
.IO(DDR3_DQ[x]), // DQ pad
.I(gowin_dq_out), // ODDR -> IOBUF
.OEN(~gowin_dq_oe) // input when 1'b1
);
IBUF gowin_dq_extra_ibuf
(
.I(DDR3_DQ[x]),
.O(gowin_ibuf_in)
);
IDDR gowin_dq_iddr_inst
(
.Q0(RDQ_l[x]), // SDR to app #0
.Q1(RDQ_h[x]), // SDR to app #1
.D(gowin_ibuf_in), // DDR input signal from extra inserted IBUF
.CLK(DDR_CLK_RDQ) // read clock
);