Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Spartan 6 - OSERDES2 to ODDR - Unroutable signals

Status
Not open for further replies.

pigtwo

Member level 4
Joined
Jul 16, 2015
Messages
70
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
2,771
Hello all,

I'm working on a simple DVI driver in a Spartan 6 and I'm running into a routing problem. To transmit the TMDS signals I'm trying to create a 10:1 serializer. I'm using two sets of OSERDES primitives each generating a 5:1 serializer then I'm using a ODDR primitive to do the final 2:1 serialization(for a total of 10:1).

The problem I'm having is ISE is saying that it can't route the signal between the OSERDES2 output to the ODDR input. The error I'm getting is:
Code:
ParHelpers:360 - Design is not completely routed.

   blueSer/evenData
   blueSer/oddData
   greenSer/evenData
   greenSer/oddData
   redSer/evenData
   redSer/oddData
   serStrobeSR_2

The code for the serializer is below:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    06:11:45 01/09/2019 
// Design Name: 
// Module Name:    Ser_10_1 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module Ser_10_1(
   input wire parClk,
   input wire serClk,
   input wire dataStrobe,
   input wire serCE,
   input wire reset,
   input wire[9:0] parData,
   
   output serData
   );
   
   parameter integer dataWidth = 5;
   
   wire cascade_do1, cascade_do2, cascade_to1, cascade_to2;
   wire cascade_di1, cascade_di2, cascade_ti1, cascade_ti2;
   wire evenData, oddData;
   
 
      // Output serializer 
   OSERDES2 #(
              .DATA_RATE_OQ("SDR"),
              .DATA_RATE_OT("SDR"),
              .DATA_WIDTH(dataWidth),
              .OUTPUT_MODE("SINGLE_ENDED"),
              .SERDES_MODE("MASTER"),
              .TRAIN_PATTERN(4'hA)
              ) serdesMaster1 (
              .CLK0(serClk),
              .CLK1(),
              .CLKDIV(parClk),
              .IOCE(dataStrobe),
              .D1(parData[8]),
              .D2(1'b0),
              .D3(1'b0),
              .D4(1'b0),
              .OCE(serCE),
              .RST(~reset),
              .T1(1'b0),
              .T2(1'b0),
              .T3(1'b0),
              .T4(1'b0),
              .TCE(1'b1),
              .SHIFTIN1(1'b1),
              .SHIFTIN2(1'b1),
              .SHIFTIN3(cascade_do1),
              .SHIFTIN4(cascade_to1),
              .TRAIN(1'b0),
              .OQ(evenData),
              .TQ(),
              .SHIFTOUT1(cascade_di1),
              .SHIFTOUT2(cascade_ti1),
              .SHIFTOUT3(),
              .SHIFTOUT4()
              );
 
   OSERDES2 #(
              .DATA_RATE_OQ("SDR"),
              .DATA_RATE_OT("SDR"),
              .DATA_WIDTH(dataWidth),
              .OUTPUT_MODE("SINGLE_ENDED"),
              .SERDES_MODE("SLAVE"),
              .TRAIN_PATTERN(4'hA)
              ) serdesSlave1 (
              .CLK0(serClk),
              .CLK1(),
              .CLKDIV(parClk),
              .IOCE(dataStrobe),
              .D1(parData[0]),
              .D2(parData[2]),
              .D3(parData[4]),
              .D4(parData[6]),
              .OCE(serCE),
              .RST(~reset),
              .T1(1'b0),
              .T2(1'b0),
              .T3(1'b0),
              .T4(1'b0),
              .TCE(1'b1),
              .SHIFTIN1(cascade_di1),
              .SHIFTIN2(cascade_ti1),
              .SHIFTIN3(1'b1),
              .SHIFTIN4(1'b1),
              .TRAIN(1'b0),
              .OQ(),
              .TQ(),
              .SHIFTOUT1(),
              .SHIFTOUT2(),
              .SHIFTOUT3(cascade_do1),
              .SHIFTOUT4(cascade_to1)
              );
 
   OSERDES2 #(
              .DATA_RATE_OQ("SDR"),
              .DATA_RATE_OT("SDR"),
              .DATA_WIDTH(dataWidth),
              .OUTPUT_MODE("SINGLE_ENDED"),
              .SERDES_MODE("MASTER"),
              .TRAIN_PATTERN(4'hA)
              ) serdesMaster2 (
              .CLK0(serClk),
              .CLK1(),
              .CLKDIV(parClk),
              .IOCE(dataStrobe),
              .D1(parData[9]),
              .D2(1'b0),
              .D3(1'b0),
              .D4(1'b0),
              .OCE(serCE),
              .RST(~reset),
              .T1(1'b0),
              .T2(1'b0),
              .T3(1'b0),
              .T4(1'b0),
              .TCE(1'b1),
              .SHIFTIN1(1'b1),
              .SHIFTIN2(1'b1),
              .SHIFTIN3(cascade_do2),
              .SHIFTIN4(cascade_to2),
              .TRAIN(1'b0),
              .OQ(oddData),
              .TQ(),
              .SHIFTOUT1(cascade_di2),
              .SHIFTOUT2(cascade_ti2),
              .SHIFTOUT3(),
              .SHIFTOUT4()
              );
 
   OSERDES2 #(
              .DATA_RATE_OQ("SDR"),
              .DATA_RATE_OT("SDR"),
              .DATA_WIDTH(dataWidth),
              .OUTPUT_MODE("SINGLE_ENDED"),
              .SERDES_MODE("SLAVE"),
              .TRAIN_PATTERN(4'hA)
              ) serdesSlave2 (
              .CLK0(serClk),
              .CLK1(),
              .CLKDIV(parClk),
              .IOCE(dataStrobe),
              .D1(parData[1]),
              .D2(parData[3]),
              .D3(parData[5]),
              .D4(parData[7]),
              .OCE(serCE),
              .RST(~reset),
              .T1(1'b0),
              .T2(1'b0),
              .T3(1'b0),
              .T4(1'b0),
              .TCE(1'b1),
              .SHIFTIN1(cascade_di2),
              .SHIFTIN2(cascade_ti2),
              .SHIFTIN3(1'b1),
              .SHIFTIN4(1'b1),
              .TRAIN(1'b0),
              .OQ(),
              .TQ(),
              .SHIFTOUT1(),
              .SHIFTOUT2(),
              .SHIFTOUT3(cascade_do2),
              .SHIFTOUT4(cascade_to2)
              );                             
  
         
   // Output DDR 
   ODDR2 #(
            .DDR_ALIGNMENT("C0"),
            .INIT(1'b0),
            .SRTYPE("ASYNC")
            ) DDROutRed (
            .D0(evenData),
            .D1(oddData),
            .C0(serClk),
            .C1(~serClk),
            .CE(serCE),
            .R(~reset),
            .S(1'b0),
            .Q(serData)
            );
 
endmodule



I can't seem to figure out what the problem here is. I've looked on the Xilinx forums but the problems other people had don't seem to be my problems. Both the clocks used in this module are given to a BUFG.

The signal serStrobeSR_2 is a bit in a shift register in the following code:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    05:37:47 12/18/2018 
// Design Name: 
// Module Name:    DVI_Driver 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module DVI_Driver(
    input wire clk50Buffer,
    input wire reset_brd,
   
   output wire redDataSer_p,
   output wire redDataSer_n,
   output wire greenDataSer_p,
   output wire greenDataSer_n,
   output wire blueDataSer_p,
   output wire blueDataSer_n,
   output wire VSYNCOut
   );
   
   // Define screen size
   parameter HPixelWidth = 1024;
   parameter VPixelWidth = 768;
   parameter blankPixelWidth = 148;  // This gives a pixel clock very close to 54MHz.
   
   // TMDS encoders singals
   wire redEnable, greenEnable, blueEnable;
   reg allEnable;
   wire redDone, greenDone, blueDone;
   reg DE, HSYNC, VSYNC;
   reg[7:0] redData, greenData, blueData;
   wire[9:0] redDataEncoded, greenDataEncoded, blueDataEncoded;
 
   assign redEnable = allEnable;
   assign greenEnable = allEnable;
   assign blueEnable = allEnable;
 
   // Serializer signals
   wire redDataSer, greenDataSer, blueDataSer;
   
   // Timing control signals
   reg[11:0] HPixelCount, VPixelCount, blankCount;
   
   // Clocking signals
   wire clk54, clk270;
   wire locked54, locked270;
   wire reset;
   
   assign reset = locked54 & locked270;
   
   // Serializer and DDR singals
   reg[4:0] serStrobeSR;
   reg serStrobe, serCE;
   
 
   // Top level outputs
   assign clk54Out = 1'b0;//clk54;
   assign clk270Out = 1'b0; //clk270;
   assign VSYNCOut = VSYNC;
   
   // Define IBUFG directly because clk50 goes to two DCMs which try to make their own BUFG.
   IBUFG clkBuffer50 ( .I(clk50Buffer), .O(clk50) );
   
   // Define output differential signals
   OBUFDS redDataDS ( .I(redDataSer), .O(redDataSer_p), .OB(redDataSer_n) );
   OBUFDS greenDataDS ( .I(greenDataSer), .O(greenDataSer_p), .OB(greenDataSer_n) );
   OBUFDS blueDataDS ( .I(blueDataSer), .O(blueDataSer_p), .OB(blueDataSer_n) );
   
   // Generate 270MHz clock
   Clock_Generator_270 gen270(
                              .CLK_IN1(clk50),
                              .CLK_OUT1(clk270),
                              .RESET(~reset_brd),
                              .LOCKED(locked270)                             
                              );
   
  
   // Generate 54MHz clk
   //    I use two separte DCMs to keep precision.  Using one to generate both clocks caused the clocks to not be exact multiples.
   Clock_Generator_54 gen54(
                            .CLK_IN1(clk50),
                            .CLK_OUT1(clk54),
                            .RESET(~reset_brd),
                            .LOCKED(locked54)
                            );
   
   
   // Red data
   TMDS_Encoder redEncoder(
                           .clk(clk54),
                           .reset(reset),
                           .enable(redEnable),
                           .DE(DE),
                           .C0(HSYNC),
                           .C1(VSYNC),
                           .rawData(redData),
                           .encodedData(redDataEncoded),
                           .done(redDone)                           
                           );
   
   // Green data
   TMDS_Encoder greenEncoder(
                           .clk(clk54),
                           .reset(reset),
                           .enable(greenEnable),
                           .DE(DE),
                           .C0(1'b0),
                           .C1(1'b0),
                           .rawData(greenData),
                           .encodedData(greenDataEncoded),
                           .done(greenDone)                           
                           );
                           
   // Blue data
   TMDS_Encoder blueEncoder(
                           .clk(clk54),
                           .reset(reset),
                           .enable(blueEnable),
                           .DE(DE),
                           .C0(1'b0),
                           .C1(1'b0),
                           .rawData(blueData),
                           .encodedData(blueDataEncoded),
                           .done(blueDone)                           
                           );
   
   
   // Red Serializer
   Ser_10_1 redSer(
                  .parClk     (clk54),
                  .serClk     (clk270),
                  .dataStrobe (serStrobe),
                  .serCE      (serCE),
                  .reset      (reset),
                  .parData    (redDataEncoded),
                  .serData    (redDataSer)
                  );
 
   // Green Serializer
   Ser_10_1 greenSer(
                  .parClk     (clk54),
                  .serClk     (clk270),
                  .dataStrobe (serStrobe),
                  .serCE      (serCE),
                  .reset      (reset),
                  .parData    (greenDataEncoded),
                  .serData    (greenDataSer)
                  );
 
   // Blue Serializer
   Ser_10_1 blueSer(
                  .parClk     (clk54),
                  .serClk     (clk270),
                  .dataStrobe (serStrobe),
                  .serCE      (serCE),
                  .reset      (reset),
                  .parData    (blueDataEncoded),
                  .serData    (blueDataSer)
                  );   
   
   // Generate serializer strobe
   always @(posedge clk270 or negedge reset) begin
      if(!reset) begin
         serStrobeSR <= 5'b00001;
         serStrobe <= 1'b0;
         serCE <= 1'b0;
      end else begin
         serCE <= 1'b1;
         serStrobeSR <= {serStrobeSR[3:0], serStrobeSR[4]};
         serStrobe <= serStrobeSR[1];
      end
   end 
   
   
   // Manage output data
   always @(posedge clk54 or negedge reset) begin
      if(!reset) begin
         allEnable = 1'b0;
         DE = 1'b0;
         HSYNC = 1'b0;
         VSYNC = 1'b0;
         redData = 8'd0;
         greenData = 8'd1;
         blueData = 8'd2;
         
         HPixelCount = 12'b0;
         VPixelCount = 12'b0;
         blankCount = 12'b0;
      end else begin
         allEnable = 1'b1;
         redData = redData + 1;
         greenData = greenData + 1;
         blueData = blueData + 1;
         
         if(HPixelCount < HPixelWidth) begin
            DE = 1'b0;
            HSYNC = 1'b0;
            VSYNC = 1'b0;
            
            HPixelCount = HPixelCount + 1'b1;
         end else begin
            DE = 1'b1;
            HSYNC = 1'b1;
 
            if(VPixelCount == VPixelWidth) begin
               VSYNC = 1'b1;
            end else begin
               VSYNC = 1'b0;
               VPixelCount = VPixelCount + 1'b1;
            end
            
            if(blankCount == blankPixelWidth) begin
               HPixelCount = 12'b0;
               VPixelCount = 12'b0;
               blankCount = 12'b0;
            end else begin
               blankCount = blankCount + 1'b1;
            end
         end
      end
   end
endmodule



Does anyone know why this might be happening? Or what I can do to try to track this down a little better?

Thank you!
 

I'm not sure this is allowed, as the SERDES are in the I/O module, i.e., the output of the SERDES goes to an output port, not back into the fabric. You might need to roll-your-own parallel-to-serial converter.
 

Have you checked ug381?
There is a following drawing which might give you a hint:
OSERDES_DDR.png

The ODDR is after 3rd OSERDES(counting 4th -> 3rd -> ODDR).
Make sure you didn't instantiated the 2nd OSERDES.
 

@barry Yep, that does seem to be my problem. I used two OSERDES2 primitives in parallel each driving one pin of the ODDR but with the image niciki posted that doesn't seem to be possible. The only reason I did this was because I need a 10 to 1 serializer but the OSERDES2 only allows a max of 8 bits. I'll just have to create another clock and load the 5:1 serializer twice as often.

@niciki Thank you for finding that for me. I only looked at the ODDR and OSERDES2 sections so I missed that. I don't believe I'm creating the third OSERDES2. But I am doing some stuff that violates that diagram. Although that diagram is a little confusing. I don't even understand how you can have 3 OSERDES2 primitives in series. The maximum data width of the OSERDES2 is 8 with each individual OSERDES2 having 4 bits. I tried simulating numbers higher than 8 but it threw a bunch of errors. Secondly, it shows the OSERDES2 output going to the ODDR input but OSERDES2 is a one bit output but ODDR is a two bit input. It's not clear to me how exactly this is resolved. I'm not really asking these questions directly. It's more just my thought process.

I think I know what I need to do now. Thanks again for the help!
 

The DDR output register is fed with half the final output data rate. This should allow to use general core registers for the 5:1 serializers. In other words make your own 10:1 OSERDES block.

If you can't achieve timing closure, you are probably beyond the capabilities of the used device family.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top