99// Package: Cosim_DpiPkg
1010//
1111// Main cosim <--> dpi bridge module.
12+
13+
1214//
1315// ===----------------------------------------------------------------------===//
1416
@@ -118,9 +120,8 @@ module Cosim_Endpoint_FromHost
118120 $error("Cosim endpoint (%s) register failed: %d" , ENDPOINT_ID, rc);
119121 end
120122
121- // / *******************
122- // / Data out management.
123- // /
123+ // / ***********************
124+ // / Useful constants.
124125
125126 localparam int FROM_HOST_SIZE_BYTES = int'((FROM_HOST_SIZE_BITS+ 7 )/ 8 );
126127 // The number of bits over a byte.
@@ -129,13 +130,30 @@ module Cosim_Endpoint_FromHost
129130 localparam int FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS
130131 = FROM_HOST_SIZE_BYTES_FLOOR * 8 ;
131132
133+ // Buffer to hold incoming data directly from the DPI calls.
132134 byte unsigned DataOutBuffer[FROM_HOST_SIZE_BYTES- 1 :0 ];
135+
136+ // Pipeline interface signals for buffering DataOut.
137+ // DataOut_a_valid is asserted when a complete message is available in
138+ // DataOut_a buffer and waiting to be accepted by the skid buffer.
139+ logic DataOut_a_valid;
140+ // Packed representation of the byte buffer to feed the skid input.
141+ logic [FROM_HOST_SIZE_BITS- 1 :0 ] DataOut_a;
142+ // Ready/valid wires between this module and the skid buffer.
143+ wire DataOut_a_ready;
144+ wire DataOut_x_valid;
145+ wire [FROM_HOST_SIZE_BITS- 1 :0 ] DataOut_x;
146+
133147 always @(posedge clk) begin
134148 if (~ rst) begin
135- if (DataOutValid && DataOutReady) // A transfer occurred.
136- DataOutValid <= 1'b0 ;
137-
138- if (! DataOutValid || DataOutReady) begin
149+ // If the skid buffer accepted the input token this cycle, clear the
150+ // internal valid that indicates we have buffered data.
151+ if (DataOut_a_valid && DataOut_a_ready)
152+ DataOut_a_valid <= 1'b0 ;
153+
154+ // Only attempt to fetch data from the host when the skid buffer can
155+ // accept it (DataOut_a_ready).
156+ if (! DataOut_a_valid && DataOut_a_ready) begin
139157 int data_limit;
140158 int rc;
141159
@@ -149,7 +167,7 @@ module Cosim_Endpoint_FromHost
149167 ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit, rc);
150168 end else if (rc == 0 ) begin
151169 if (data_limit == FROM_HOST_SIZE_BYTES)
152- DataOutValid <= 1'b1 ;
170+ DataOut_a_valid <= 1'b1 ;
153171 else if (data_limit == 0 )
154172 begin end // No message.
155173 else
@@ -159,24 +177,53 @@ module Cosim_Endpoint_FromHost
159177 end
160178 end
161179 end else begin
162- DataOutValid <= 1'b0 ;
180+ DataOut_a_valid <= 1'b0 ;
163181 end
164182 end
165183
166- // Assign packed output bit array from unpacked byte array.
184+ // Pack the byte array into a single vector that will be handed to the
185+ // skid buffer as its input payload.
167186 genvar iOut;
168187 generate
169188 for (iOut= 0 ; iOut< FROM_HOST_SIZE_BYTES_FLOOR; iOut++ )
170- assign DataOut [((iOut+ 1 )* 8 )- 1 :iOut* 8 ] = DataOutBuffer[iOut];
189+ assign DataOut_a [((iOut+ 1 )* 8 )- 1 :iOut* 8 ] = DataOutBuffer[iOut];
171190 if (FROM_HOST_SIZE_BITS_DIFF != 0 )
172- // If the type is not a multiple of 8, we've got to copy the extra bits.
173- assign DataOut [(FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS +
174- FROM_HOST_SIZE_BITS_DIFF - 1 ) :
175- FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS]
191+ // If the type is not a multiple of 8, copy the extra bits.
192+ assign DataOut_a [(FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS +
193+ FROM_HOST_SIZE_BITS_DIFF - 1 ) :
194+ FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS]
176195 = DataOutBuffer[FROM_HOST_SIZE_BYTES - 1 ]
177196 [FROM_HOST_SIZE_BITS_DIFF - 1 : 0 ];
178197 endgenerate
179198
199+ // / *******************
200+ // / Data out management.
201+ // /
202+ // / It has been observed that some simulators (verilator) does not handle
203+ // / combinational driving from DPI well (resulting in non-determinism wrt
204+ // / some of the combinational outputs being dropped/replicated). Questa does
205+ // / not show this behavior.
206+ // / A mitigation is to add a skid buffer to decouple the DPI interface
207+ // / from the output interface.
208+
209+ // Instantiate a single-stage pipeline to buffer tokens that arrive from
210+ // the host and present them to the module's output with proper
211+ // ready/valid handshaking.
212+ ESI_PipelineStage #(.WIDTH(FROM_HOST_SIZE_BITS)) out_pipe (
213+ .clk(clk),
214+ .rst(rst),
215+ .a_valid(DataOut_a_valid),
216+ .a(DataOut_a),
217+ .a_ready(DataOut_a_ready),
218+ .x_valid(DataOut_x_valid),
219+ .x (DataOut_x),
220+ .x_ready(DataOutReady)
221+ );
222+
223+ // Drive the module's outward-facing signals from the pipeline output.
224+ assign DataOutValid = DataOut_x_valid;
225+ assign DataOut = DataOut_x;
226+
180227 initial begin
181228 $display ("FROM_HOST_SIZE_BITS: %d" , FROM_HOST_SIZE_BITS);
182229 $display ("FROM_HOST_SIZE_BYTES: %d" , FROM_HOST_SIZE_BYTES);
0 commit comments