Author Topic: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.  (Read 60198 times)

0 Members and 3 Guests are viewing this topic.

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #200 on: August 30, 2022, 06:09:30 am »
That's better. Fixed the phase. I'll upload the changes in the morning (to the quick-test) and copy gowin_ddr_clocking.sv over to the full repo after I've tested it out there too. It ought to just drop in, but ... famous last words...
 

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #201 on: August 30, 2022, 06:22:36 am »
Umm, shouldn't the 133MHz be 100MHz?
Maybe a typo in the divider.

Yeah, they worried me too at first, but it's just the CLKOUTD3 - fixed division of the CLKOUT by 3. Notice there's 8 clocks listed there, and I only want 5 of them - I burn a zero-phase-offset 400MHz output (because I get 2 of them) and I get two 133's "for free" as the /3 of the 400's.

Or if it's another output, maybe set it to 100MHz and place it on the first PLL reserving the write clock to PLL2.
(This is a plus in the future as you may use the 'delay' output primitive for the write data removing the need for the second PLL all together.  Though, get my DDR3 working firstly as intended.)

Sadly, there's no configuration for that output - it's /3 and that's your lot.


Also for the duty cycle, why not just hard write it in the parameter line just as if it came from the rPLL GUI generator?
There's a comment in the code about the write-clock being 90 or 270 degrees out of phase - maybe it's always 270 ?, anyway, it doesn't take much, the table is only 16 entries long, so I just created another 16-entries table and offset it by the phase.

Next, take a look at IO buffer primitives, then, the DDR primitives to drive those buffers.

DDR3_CK needs a differential LVDS output.  (May also be 2 output pin buffers, but this is lower quality.)
DDR3_DQS needs a differential LVDS bidirectional.  (May also be 2 bidir pin buffers, but this is lower quality.)

Yep, I've been looking at that a little. There's not too much to configure for DDR - I don't see any Differential DDR for example, the tool offers as below. I've done (this is all pre-testing) the command bus signals, which are relatively straightforward, and I implemented the n{CK} as 2 output buffers each with complementary drive. I'm not sure I have much in the way of options here...
 

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #202 on: August 30, 2022, 06:28:20 am »
The DDR doesn't drive the PIN, it is the IO buffers which drive the pins.
The DDR <-> IO buffers <-> pin.
Read your Gowin documentation and you will understand the DDR primitive outputs, where they are tied to.
All the different type of IO buffers are right at the beginning of the primitives.

(I know Altera stuffed these 2 into a single primitive, Gowin does not...)
« Last Edit: August 30, 2022, 06:40:32 am by BrianHG »
 

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #203 on: August 30, 2022, 06:39:51 am »
I see, so chain the DDR output through an TLVDS_OBUF (or ELVDS_OBUF) for outputs, and *_TBUF for bidirectional signals. Ok, that makes sense, I’ll try integrating that into what I have.

Anyway (yawn) I’m done for the day, I’m up in 6 hours…
 

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #204 on: August 31, 2022, 02:39:47 am »
So here's a question...

As given, the DDR input/output construct from Gowin doesn't have any obvious built in way to set a different clock on the input and output routes, like the Altera one seems to have.

Code: [Select]
`timescale 100 ps/100 ps
module Gowin_DDR (
  din,
  tx,
  clk,
  io,
  q
)
;
input [1:0] din;
input [0:0] tx;
input clk;
inout [0:0] io;
output [1:0] q;
wire [0:0] iobuf_o;
wire [0:0] ddr_inst_q0;
wire [0:0] ddr_inst_q1;
wire VCC;
wire GND;
  IOBUF \ddr_gen[0].iobuf_inst  (
    .O(iobuf_o[0]),
    .IO(io[0]),
    .I(ddr_inst_q0[0]),
    .OEN(ddr_inst_q1[0])
);
  ODDR \ddrx1_gen[0].oddr_inst  (
    .Q0(ddr_inst_q0[0]),
    .Q1(ddr_inst_q1[0]),
    .D0(din[0]),
    .D1(din[1]),
    .TX(tx[0]),
    .CLK(clk)
);
  IDDR \ddrx1_gen[0].iddr_inst  (
    .Q0(q[0]),
    .Q1(q[1]),
    .D(iobuf_o[0]),
    .CLK(clk)
);
  VCC VCC_cZ (
    .V(VCC)
);
  GND GND_cZ (
    .G(GND)
);
  GSR GSR (
    .GSRI(VCC)
);
endmodule /* Gowin_DDR */


I could, of course, pass in the 2 clocks and just wire up the IDDR to the read-clock and the ODDR to the write-clock. The obvious problem is that the direction control OEN on the IOBUF, which is linked to Q1 on the ODDR, in turn linked through to TX on the input is going to always be in the phase of the write-clock

The question is: does this matter ?

Looking at the signalling for DDR3, it seems there's a whole bunch of cycles before DQ is read/written or DQS* are asserted, and successive READ and WRITE ops will presumably need that preamble, so if the TX is set during that preamble, and held for the duration of the operation, I'll be fine just wiring up the data to the correct clocks, I think.

Of course, I could be wrong about that, and it's also possible that TX is controlled per-cycle, hence the question...
 

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #205 on: August 31, 2022, 02:58:21 am »
Don't worry about the details yet.

Make a bit width sizable ddr bidir with 2 clocks, 1 in, 1 out.
The DDR output should take in the OE in parallel with it's data and posedge clock out.
The read side does nothing but DDR read the t pin buffer.

We will worry about the 'half-clock' delayed OE feature I use with Altera later.
(I use it to half clock early turn on the OE and half clock late turn it off, expanding the OE's timing for severe overclocking performance.  I'm sure we can adapt Gowin, or just use the parallel OE without my expansion feature.)

All DDR buffers run exclusively on positive edge clocked logic.  Otherwise, what it the point of the DDR primitive?  Otherwise I could have done half my buffers in posedge clk and the other half in negedge clock and never use any DDR primitives on any FPGA and the world would be perfect.


If you are not sure how the Altera ddr buffer works, you can add the port IO traces to the sim and watch, or go to Altera's data sheet I posted a few threads ago.
« Last Edit: August 31, 2022, 03:01:33 am by BrianHG »
 
The following users thanked this post: SpacedCowboy

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #206 on: August 31, 2022, 03:03:11 am »
Remember, Gowin's DDR out has an input for TX enable and passes that signal to the OEn for the tristate buffer.
 

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #207 on: September 01, 2022, 12:04:22 am »
So I figured out what I thought I was going to do (it's easier to draw for 2-bits rather than N*2-bits)...

Code: [Select]
     ┌─────────────┐      ┌───────────┐      ┌─────────────┐         
     │    Module   │      │   IDDR    │      │ TLVDS_IOBUF │         
     │             │      │           │      │             │         
     │             │      │           │      │             │         
────▶│    rdClk    │─────▶│ CLK       │      │             │         
     │             │      │           │      │             │         
     │             │      │    D [DDR]│◀─────┤ O [DDR]     │         
     │             │      │           │      │             │         
◀────┤rdData[1:0]  │ ◀────┤Q[1:0]     │      │             │         
     │             │      │(SDR)      │      │             │         
     │             │      └───────────┘      │             │  IO+   
     │             │                         │             ├────▶   
     │             │      ┌───────────┐      │             │         
     │             │      │   ODDR    │      │             │         
     │             │      │           │      │             ├────▶   
────▶│    wrClk    │─────▶│ CLK       │      │             │  IO-   
     │             │      │           │      │             │         
────▶│   txEnable  │─────▶│ TX        │      │             │         
     │             │      │           │      │             │         
     │             │      │   Q1 [DDR]├─────▶│OEN (DDR)    │         
     │             │      │           │      │             │         
     │             │      │   Q0 [DDR]├─────▶│I [DDR]      │         
     │             │      │           │      │             │         
────▶│wrData[1:0]  │─────▶│Q[1:0]     │      │             │         
     │             │      │(SDR)      │      │             │         
     └─────────────┘      └───────────┘      └─────────────┘         

... and then for N*2 bits, the last 2 columns are replicated by N with the data routed appropriately.

And then I looked closer at the DQS signaling inside the generate(..) and it looks as though you never actually read the signal from the DDR3 when it's in read-mode anyway :) 

Code: [Select]
         ...
        .inclock         (DDR_CLK_RDQ),            .outclock        (DDR_CLK),
        .dout            ({RDQS_ph[x],RDQS_pl[x]}),.din             ( 2'b10 ),   
        .pad_io         (DDR3_DQS_p[x]),          .pad_io_b        (DDR3_DQS_n[x]),              .oe         (OE_DQS[x]),
         ...

So, clock pins {_p,_n} are write-only, DQS pins {_p,_n} are really write-only (the read port outputs 2'b10). The other pins on the chip can be DDR, but they're not differential.
 

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #208 on: September 01, 2022, 01:01:10 am »

And then I looked closer at the DQS signaling inside the generate(..) and it looks as though you never actually read the signal from the DDR3 when it's in read-mode anyway :) 


Ohhh, yes I do...

#1) Differential LVDS IO pin version, MAX IO : BrianHG_DDR3_IO_PORT_ALTERA.sv#L278

#2) Emulated LVDS IO pin version, old Cyclone IO : BrianHG_DDR3_IO_PORT_ALTERA.sv#L390

#3) Reading in the DQ data to my primary shift register : BrianHG_DDR3_IO_PORT_ALTERA.sv#L507

#4) Reading in the DQS status to my primary shift register : BrianHG_DDR3_IO_PORT_ALTERA.sv#L511

#5) AND HERE IS THE KICKER -> Qualifying the beginning of the read location by reading the DQS contents : BrianHG_DDR3_IO_PORT_ALTERA.sv#L524

If you are using the differential pad, then you need to use the MAX buffer #1), if you are using emulated differential pad (more compatible), then use the Cyclone buffer #2).

(Also, my 2 bit array 'RDQ_POS' is the only 2 bit counter in this 400MHz section.  There is no other logic or tests of bits which exceed 2 bits.  Everything else is 1bit along a fixed parameter position of shift registers.)
« Last Edit: September 01, 2022, 01:11:39 am by BrianHG »
 

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #209 on: September 01, 2022, 03:20:17 am »
Ah, ok. I had the sense of the signals the wrong way around (equating .din with read). It makes sense that to-DDR3 should be a fixed clock and from-DDR3 is read in.

Ok, well the diagram it is, then :)
 

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #210 on: September 01, 2022, 03:25:26 am »
Outclock samples the outdata and oe to transmit the outdata.
Inclock clocks the data coming in from the IO pin to the indata.

I'm assuming gowin's DDR in[0] is the low data and the in[1] if the high data.  I think in[1] is presented first, or is delayed after outputing the first in[0].  I guess we need to see a timing diagram example.
« Last Edit: September 01, 2022, 03:28:59 am by BrianHG »
 

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #211 on: September 01, 2022, 03:29:29 am »
Yep, that's what I'm trying to convey above. Given the Gowin setup with TX,Q on ODDR being sampled using the same clock, it's harder *not* to do that.
 

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #212 on: September 01, 2022, 03:35:07 am »
Outclock samples the outdata and oe to transmit the outdata.  (called din on the altera primitive)
Inclock clocks the data coming in from the IO pin to the indata. (called dout on the altera primitive)

I'm assuming gowin's DDR in[0] is the low data and the in[1] if the high data.  I think in[1] is presented first, or is delayed after outputing the first in[0].  I guess we need to see a timing diagram example.

I hate these confusing port naming BS!
They should have called it TX data and RX data if they really wanted to not confuse things.
« Last Edit: September 01, 2022, 03:51:25 am by BrianHG »
 

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #213 on: September 01, 2022, 11:20:49 pm »
Well?  You did the PLL fast and the DDR is a fraction the complexity...
 

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #214 on: September 02, 2022, 12:28:23 am »
It's funny. I found the PLL much easier to grok than the DDIO/LVDS stuff - I guess I've instantiated PLLs dozens of times (if not with Gowin) but never actually used DDIO before ...

I'll get back to it tomorrow evening, but tomorrow @ 9AM I have to (at least partly) present the 2023 feature-roadmap to a bunch of VPs/SVPs (most of whom want to go in different directions from each other, which will make the meeting ... interesting) It's been a busy week of finalizing cross-functional support/dependencies and horse-trading features, loaning out engineers if necessary, etc. etc.
 

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #215 on: September 04, 2022, 02:47:33 am »
So, some progress - see "offset-signals" below. Altera signals in green, gowin equivalents in cyan directly underneath.

It's certainly not working yet. The Gowin primitives seem to add a couple of clocks of latency between input and output, which is expected behavior from the GPIO user guide - extract below as gowin-oddr-timing.

There's also issues with polarity, and I'm not completely sure I've tracked all those down yet. The gowin OE signal (they call it TX) is output-active on tx=1'b0, not 1'b1. The LVDS channels seems to be inverted as well, but that might be a corollary of the timing being off.

In any event, the simulation isn't returning data yet, but it's enough for today. Code is checked in.
 

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #216 on: September 04, 2022, 03:01:45 am »
Phase and delay clock offsets don't matter.
This is why I pass absolutely everything through the DDR when feeding the DDR3 ram chips.  If the command is delayed with the clocks, then the data going out will match the delay as well.  Your biggest issue should only be getting the [0:1]  input orientation correct so that the commands out look correct.  (The orientation for every DDR out should match.  The read input may have this orientation backwards.)

There is a calibration clock cycle offset for reading in the data, but let's worry about that one second.
Your first goal is to feed the first MRS commands at startup.

Then we see if the read will need a + or - 1 cycle tuning.  My code has room for - 2 clocks, + >4 clocks levels of adjustment.
What we will do here is add a localparam Gowen_read_correction = x  and add it to my set offset when the right Gowin FPGA is set for the vendor parameter.

There is one other adjustment regarding the OE cycle delay.  I have once again tuning controls for this, but, I would like to try to replicate my 'half' clock cycle I'm using with Altera, but is is not mandatory,  You will need to check with Gowin's TX command and see if it's output can be shifted to activate on the rise or fall of reference CLK in's output time slot.  Altera has a parameter for their DDR to choose this optional delay.  Note that all commands going into the DDR primitive should always be active on the rising clock.
« Last Edit: September 04, 2022, 03:39:20 am by BrianHG »
 
The following users thanked this post: SpacedCowboy

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #217 on: September 04, 2022, 03:23:10 am »
Note that because of the read clock calibration, my code can get stuck in the tuning power-up sequence stage, but first let's make the commands output look correct.

Second, Gowin's txclk_pol parameter appears to perform the 'half-shift' operation for the OE which I was describing above.
 

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #218 on: September 04, 2022, 07:35:48 pm »
Okay, so everything seems to start off ok, we get the following command sequence from startup, see 'MRS2 signals' for an example...

Code: [Select]
MRS, BA=2: Write MR2 to 16’h0000
- A[10:9] = 2’b0 Dynamic ODT off
- A[7] = 1’b0 Normal operating temperature range
- A[6] = 1’b0 Manual Self-refresh reference
- A[5:3] = 3’b0 CAS write latency of 5 (>= 2.5ns)
- A[2:0] = 3’b0 Full array self-refresh

MRS, BA=3: Write MR3 to 16’h0000
- A[2] =1’b0 MPR = normal operation
- A[1:0] = 2’b0 (ignored anyway)

MRS, BA=1: Write MR1 to 16’h0044
- A[12] = 1’b0 Output buffer enables
- A[11] = 1’b0 TDQS disabled
- A[9,6,2] = 3’b011 Rtt_Nom = RZQ/6
- A[7] = 1’b0 Write leveling disabled
- A[5,1] = 2’b0 (reserved for RZQ/6)
- A[0] = 1’b0 DLL enabled

MRS,  BA=0: Write MR0 to 16’h1720
- A[12] = 1’b1 DLL control for Precharge, fast-exit (DLL on)
- A[11:9] = 3’b011 Write recovery for autoprecharge = 7 cycles
- A[8] = 1’b1 DLL Reset = Yes
- A[7] = 1’b0 Test mode disabled
- A[6:4,2] = 4’b0100 CAS latency = 6
- A[3] = 1’b0 Nibble sequential read burst type
- A[1:0] = 2’b00 Burst length 8 (fixed)

ZQC
-A[10] = 1’b1 Do a long ZQC calibration

MRS, BA=3: Write MR3 to 16’h0004
- A[2] = 1’b1 Dataflow from MPR
- A[1:0] = 2’b00 Predefined system timing calibration pattern

 REA, BA=0, A=16’h1000
- A[12] = 1’b1 user regular burst length of 8
But the last command above (read) hits a problem. Signals attached ('REA command signaling'). Looks like DQS/DQ just aren't doing anything in the Gowin world. Could be I've just wired it wrong, but I'll have a look later-on today / this evening.
 

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #219 on: September 04, 2022, 08:15:50 pm »
@SpacedCowboy, it is no longer of any use to have side-by-side Gowin vs Altera comparisons.
Make the system Gowin only so that it matches what my Altera only sims looks like.
(Other than the 2 additional pipeline delay of Gowin's DDR buffer.  :( 2 clocks... I though maybe 1 or 1/2, but a full 2 clock delay.)
The default regs I have on the waveform display should tell you 99% of what you need to know.

Once this is organized, we need to see why Micron's DDR3 data output during the read-cal test pattern [FFFF,0000,FFFF,0000,FFFF,0000] isn't getting through Gowin's IO buffer read input.

The best way is to run 2x Modelsim, 1 with my original Altera, the other with your build.
Align the display and zoom on both and inspect the read buffer results which are included in my default display.

Remember, 2 clock means the entire read pattern is completely missed.  And, if Gowin's DDR input primitive also adds another 2 clock delays, then we need to add 4 clocks to my DDR3 controllers read reference window.  We can compare this with the 2 different snapshots once you cleaned up your current setup.
« Last Edit: September 04, 2022, 08:33:05 pm by BrianHG »
 

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #220 on: September 05, 2022, 12:08:29 am »
@SpacedCowboy, it is no longer of any use to have side-by-side Gowin vs Altera comparisons.
Make the system Gowin only so that it matches what my Altera only sims looks like.

(Other than the 2 additional pipeline delay of Gowin's DDR buffer.  :( 2 clocks... I though maybe 1 or 1/2, but a full 2 clock delay.)
The default regs I have on the waveform display should tell you 99% of what you need to know.

Once this is organized, we need to see why Micron's DDR3 data output during the read-cal test pattern [FFFF,0000,FFFF,0000,FFFF,0000] isn't getting through Gowin's IO buffer read input.

Yes, on further examination, at least some (maybe most) of the problem is that I'm trying to mimic the Altera signals for comparison, but those mimicked signals don't route into subsequent logic. I'm separating stuff out as you suggest. For the time being I'll make a similar module to BrianHG_DDR3_IO_PORT_ALTERA.sv (probably called DDR3_IO_PORT_GOWIN.sv) and put the Gowin code in there. There is a little bit of probably-duplicated code at the end, but maybe that's extractable as a module in its own right.

The best way is to run 2x Modelsim, 1 with my original Altera, the other with your build.
Align the display and zoom on both and inspect the read buffer results which are included in my default display.

Yep, I have that setup now. Large monitors are great :)

Remember, 2 clock means the entire read pattern is completely missed.  And, if Gowin's DDR input primitive also adds another 2 clock delays, then we need to add 4 clocks to my DDR3 controllers read reference window.  We can compare this with the 2 different snapshots once you cleaned up your current setup.

Noted.

I think I hadn't quite appreciated the logic for DQS read, though - my original idea was that it looked like this

Code: [Select]

 rDQS[1:0]▲        rClk│                              2'b10 │    TX│  wClk│     
          │            ▼                                    ▼      ▼      ▼     
       ┌───────────────────┐                             ┌───────────────────┐   
       │       IDDR        │                             │       ODDR        │   
       └───────────────────┘                             └───────────────────┘   
                ▲                                    OEN(DDR)│          │I(DDR) 
                │O(DDR)                                      ▼          ▼       
       ┌────────┴────────────────────────────────────────────────────────────┐   
       │                             TLVDS_IOBUF                             │   
       └─────────────────────────────────────────────────────────────────────┘   
                                      IO+│   │IO-                               
                                         │   │                                   
                                         ▼   ▼                                   

But in fact, from reading the verilog, you want to preserve 4 signals for the captured (rDQS above) DQS from the DDR3 - it wants _p and _n for both bits of the DDR signal (l and h). The code uses the _p and _n signals to determine a zero-state, so the layout really wants to look like...

Code: [Select]
                                                                                 
rDQS_n[1:0]▲        rClk│    rDQS_p[1:0]▲    rClk│     2'b10 │    TX│  wClk│     
           │            ▼               │        ▼           ▼      ▼      ▼     
        ┌───────────────────┐    ┌───────────────────┐    ┌───────────────────┐   
        │       IDDR        │    │       IDDR        │    │       ODDR        │   
        └───────────────────┘    └───────────────────┘    └───────────────────┘   
                 ▲                        ▲           OEN(DDR)│          │I(DDR) 
                 │IO-                     │IO+                ▼          ▼       
                 │                        │               ┌───────────────────┐   
                 │                        │               │    TLVDS_OBUF     │   
                 │                        │               └───────────────────┘   
                 │                        │                   IO+│   │IO-         
                 │                        └──────────────────────┤   │           
                 │                                               ▼   │           
                 └───────────────────────────────────────────────────┤           
                                                                     ▼           

I'm hoping there won't be any problems connecting an IDDR to the same pad as an LVDS_OBUF - there's only one driver of the signals, but the IDDR primitive says it needs to connect to an IBUF 'I' (not 'IO/IOB') port. I'm not sure if I'll have "used up" my IBUF for that pad by instantiating the IOBUF, next up is to see if that's the case...
 
 

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #221 on: September 05, 2022, 12:26:28 am »

Code: [Select]

 rDQS[1:0]▲        rClk│                              2'b10 │    TX│  wClk│     
          │            ▼                                    ▼      ▼      ▼     
       ┌───────────────────┐                             ┌───────────────────┐   
       │       IDDR        │                             │       ODDR        │   
       └───────────────────┘                             └───────────────────┘   
                ▲                                    OEN(DDR)│          │I(DDR) 
                │O(DDR)                                      ▼          ▼       
       ┌────────┴────────────────────────────────────────────────────────────┐   
       │                             TLVDS_IOBUF                             │   
       └─────────────────────────────────────────────────────────────────────┘   
                                      IO+│   │IO-                               
                                         │   │                                   
                                         ▼   ▼                                   

But in fact, from reading the verilog, you want to preserve 4 signals for the captured (rDQS above) DQS from the DDR3 - it wants _p and _n for both bits of the DDR signal (l and h). The code uses the _p and _n signals to determine a zero-state, so the layout really wants to look like...
Your above illustration here is the proper differential one.  My code actually ignores the _n in the read of the DQS.  However, you should 'assign _n = !_p' variant of the read signal so if I did, that logic will be properly pruned out of my design yet still function.

Quote
Code: [Select]
                                                                                 
rDQS_n[1:0]▲        rClk│    rDQS_p[1:0]▲    rClk│     2'b10 │    TX│  wClk│     
           │            ▼               │        ▼           ▼      ▼      ▼     
        ┌───────────────────┐    ┌───────────────────┐    ┌───────────────────┐   
        │       IDDR        │    │       IDDR        │    │       ODDR        │   
        └───────────────────┘    └───────────────────┘    └───────────────────┘   
                 ▲                        ▲           OEN(DDR)│          │I(DDR) 
                 │IO-                     │IO+                ▼          ▼       
                 │                        │               ┌───────────────────┐   
                 │                        │               │    TLVDS_OBUF     │   
                 │                        │               └───────────────────┘   
                 │                        │                   IO+│   │IO-         
                 │                        └──────────────────────┤   │           
                 │                                               ▼   │           
                 └───────────────────────────────────────────────────┤           
                                                                     ▼           

I'm hoping there won't be any problems connecting an IDDR to the same pad as an LVDS_OBUF - there's only one driver of the signals, but the IDDR primitive says it needs to connect to an IBUF 'I' (not 'IO/IOB') port. I'm not sure if I'll have "used up" my IBUF for that pad by instantiating the IOBUF, next up is to see if that's the case...

For the DQS, no, do not use this illustration.  This use of the IO buffer will bypass the differential input receiver which has improved noise and level immunity.

Also, for the DQ, please try to use the IO buffer's proper read back port.
« Last Edit: September 05, 2022, 12:30:15 am by BrianHG »
 
The following users thanked this post: SpacedCowboy

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #222 on: September 05, 2022, 01:01:03 am »
I still think it would have been easier for you to make your:

My_Gowin_IO_DDR_buffer
&
My_Gowin_IO_DDR_buffer_differential

With a parameter of bits_width and shove it into my IO port code under another selection of FPGA type besides the MAX_10 fpga and cyclone type fpga.
 

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #223 on: September 05, 2022, 01:17:30 am »
Take a look at my DQS DDR IO primitive here:
https://github.com/BrianHGinc/BrianHG-DDR3-Controller/blob/c901baa0c41ae46389940ae729cc772c8d40a8f1/BrianHG_DDR3/BrianHG_DDR3_IO_PORT_ALTERA.sv#L282

See, I do not use the _n which I have here:
https://github.com/BrianHGinc/BrianHG-DDR3-Controller/blob/c901baa0c41ae46389940ae729cc772c8d40a8f1/BrianHG_DDR3/BrianHG_DDR3_IO_PORT_ALTERA.sv#L393

The RDQS_nh[] and RDQS_nl[] are dummy placeholders for the old Cyclone 'software differential' style buffer since it cannot use true differential like the first MAX10 DDR primitive in this bidir case.
 

Offline SpacedCowboy

  • Frequent Contributor
  • **
  • Posts: 292
  • Country: gb
  • Aging physicist
Re: BrianHG_DDR3_CONTROLLER open source DDR3 controller. NEW v1.60.
« Reply #224 on: September 05, 2022, 01:45:49 am »
Good. The original sketch seemed "neater" to me anyway.

You're probably right about the approach - but Gowin IDDR/ODDR don't take vector arguments as the Altera ones seem to do. I could probably have bunched them up and used generate though, and kept it a little more generic. I'm generally of the school of thought "get it working" before "get it working well" and since there's a lot here that's new, keeping it simple where I can is "a good idea", at least to start off with. I think your abilities in the FPGA realm are orders of magnitude better than my own, so it's not surprising that we might tackle things differently :)

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf