- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This will be a contrived example to illustrate a point. I'll start from an incredibly simple module design that does nothing but hold output pins in a constant pattern.
module fpga_tester(
output logic test_byte
);
initial test_byte = 8'b1010_1010;
endmodule
Building that in Quartus works as expected. I get a message that the output pins are being tied high and low following the 10101010 pattern. Now, let's try doing the same exact thing, but this time using a structure in the middle. Create a structure, initialize it with the same 10101010, and assign its data to the output pins. The behavior should not change. typedef struct {
logic some_byte;
} my_struct;
module fpga_tester(
output logic test_byte
);
my_struct test_struct;
initial test_struct.some_byte = 8'b1010_1010;
assign test_byte = test_struct.some_byte;
endmodule
The result: success. This leads to the exact same result as the previous code. This is where I get confused. Interfaces, as far as I understand them, allow me to pass register data. That works for me in ModelSim. However, let's rewrite the struct version of the code to use an interface. interface my_interface;
logic some_byte;
endinterface
module fpga_tester(
output logic test_byte
);
my_interface test_interface();
initial test_interface.some_byte = 8'b1010_1010;
assign test_byte = test_interface.some_byte;
endmodule
The result: failure in Quartus. All the output pins are grounded. This gives me the impression that I shouldn't use Interfaces with any logic containing registers, because I cannot predict the result in Quartus. If I run this Interface version in ModelSim, it behaves as I would expect and shows the output pattern of 10101010. I realize there are workarounds for this specific example. I could easily change the "initial" statement to "assign" and get a continuous assignment that works to hold the output pins in the 10101010 pattern. However, I'm trying to use this example to show a larger problem, which is that interfaces in Quartus don't seem to properly support registers. I originally tried using interfaces in a more complicated design and found that Quartus synthesis results did not match simulation despite the build not having any errors. That led to me making simple test cases like this to see what works and what doesn't. I get the impression that interface support in Quartus is unpredictable. Is that something that may change, or should I stick with structs?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
To Quartus' credit, it appears to be complaining about your code before removing the registers.
Warning (12161): Node "my_interface:test_interface|my_interface.some_byte" is stuck at GND because node is in wire loop and does not have a source
i.e. maybe explore the problem with a slightly more complicated example closer to your actual problem you've run into? --- Quote Start --- However, I'm trying to use this example to show a larger problem, which is that interfaces in Quartus don't seem to properly support registers. --- Quote End --- As-is, I think I would qualify the problem further as "Quartus doesn't seem to properly support initial statements for registers in interfaces that do not have any sources to drive them", which I'm guessing is not your actual problem in your actual project.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for replying.
I think I may have misunderstood what interfaces are. I went through some tutorials that basically described them as a more advanced version of a struct including bidirectional ports and assignments/functions/tasks. Based on that, I thought an interface could “contain” a register in the same way a struct or module does. ModelSim was fine with that mentality, but I think Quartus is taking the perspective that an interface is literally just a bundle of wires. That is why the initial statement works as expected for structs, but not for interfaces. There’s no initial statement for wires. I found a verbose workaround based on the assumption that registers are only allowed outside of interfaces. In this case I treated the interface as being only a wire and added a continuous assignment from the interface wire to a register outside of the interface.interface my_interface;
logic some_byte;
endinterface
module fpga_tester(
output logic test_byte
);
my_interface test_interface(); //Create an interface instance.
assign test_byte = test_interface.some_byte; //Top level output comes from interface.
logic sample_value; //Test "register"
initial sample_value = 8'b1010_1010; //Initialize
assign test_interface.some_byte = sample_value; //Continuous assignment to interface of register value
endmodule
This approach seems like it will lead to a lot of redundant code in practice, but Quartus at least builds it into hardware with behavior that matches simulation. On the subject of complaints from Quartus, instantiating an interface always causes Quartus to tell me the interface is nothing but dangling pins. That happens even if the synthesized design works as expected. I can put in example interface code from Doulos or even Altera, and Quartus will still complain about how all the pins are dangling. I found previous forum posts about the dangling pin warning where it looked like the consensus was to just ignore it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In the examples you showed us, you are not passing the interface through any ports, you are just using it exactly like a module.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That is part of what I’m saying my issues are. I was under the impression that an interface is an entity like a module, not merely a collection of wires. I am specifically trying to use an interface like a module in the examples. I thought that was allowed, and ModelSim was okay with it. I didn't see why it wouldn't be synthesizable that way.
I can expand the original problematic example by creating a couple modules that use the interface to show that passing the interface through ports does not make a difference regarding the behavior.interface my_interface;
logic some_byte;
endinterface
module fpga_tester(
output logic test_byte
);
//Create an interface instance
my_interface test_interface();
//Use the interface instance to bridge between two modules
data_creator m_create(.test_interface);
pass_through m_pass(.test_interface, .byte_out(test_byte));
endmodule
module data_creator(
my_interface test_interface
);
initial test_interface.some_byte = 8'b1010_1010;
endmodule
module pass_through(
my_interface test_interface,
output logic byte_out
);
assign byte_out = test_interface.some_byte;
endmodule
The output pins still all end up grounded. I keep including the initial statement in the code because that's what caused the problems in my real design. I tried adding an interface to simplify ports, and suddenly the synthesis results stopped matching simulation. It came down to Quartus ignoring all the initial statements for registers that were part of the interface. I needed everything to start with specific arbitrary values (which worked fine before adding the interface), but the inclusion of an interface forced all the registers inside it to always initialize to 0.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Possibly review the "Register Power-Up Values in Altera Devices" section of the recommended coding guidelines: http://www.altera.com/literature/hb/qts/qts_qii51007.pdf
If your real code has clock and resets, add them in to try to get your bearings. On the surface, what you're trying to do isn't that different from Example 13-37. For example, regarding your 'data_creator' module above, I believe you will get good results if instead of the 'initial' statement you had it as the reset condition.
....
if( ~reset_n )
test_interface.some_byte = 8'b1010_1010;
else
test_interface.some_byte = foo;
....
Regarding using interfaces to clean up your code: I believe that your 'initial' statements (if you ever get them working) can be placed in the interface definition itself instead of within the instantiating module. Then, you can also add task methods for manipulating the ports.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In "Controlling the Power-Up State of Verilog HDL Designs," Altera says:
--- Quote Start --- In Integrated Synthesis, the initial value corresponds to the power-up state of the object that models the variable in the synthesized design. For example, if a variable represents an inferred register, then the variable's initial value corresponds to the register's power-up level. By translating initial values into power-up conditions, Integrated Synthesis ensures that the behavior of the synthesized design matches the simulated behavior of your design as closely as possible. Quartus II Integrated Synthesis honors initial values on variables and signals when possible. It honors initial values on I/O and combinational nets with no drivers. It also honors initial values on inferred registers and memories if your target device supports initialization of memories and registers. Integrated Synthesis does not honor initial values on inferred latches or combinational nets with actual drivers. In Verilog, you can specify a variable's initial value in an initial construct or in the variable's declaration itself. For example, the following Verilog fragment uses an initial construct to assign an initial value to the variable enable: reg enable; initial begin enable = 1'b1; end --- Quote End --- I tried initial statements inside the interface declaration, but it did not help. No matter where I put the initial block, it gets ignored if it's dealing with anything in an interface. Initial blocks work in practice for standalone (not inside an interface) registers, ram, and structures in Quartus. My real design has clocks in it, but unfortunately no resets. I'd rather not have to add reset networks to existing code just to be able to use interfaces. It's an interesting point about resets, though, since Quartus also takes power-up values from the reset condition coded for synchronous logic. For a goofy experiment, I rewrote my example above to add a completely unused clock and reset line to the design. Since the clock and reset values are hard coded, the clock will never toggle and the reset will never assert:interface my_interface;
logic some_byte;
endinterface
module fpga_tester(
output logic test_byte
);
//Create an interface instance
my_interface test_interface();
//Use the interface instance to bridge between two modules
data_creator m_create(.test_interface, .clk('0), .reset('0));
pass_through m_pass(.test_interface, .byte_out(test_byte));
endmodule
module data_creator(
my_interface test_interface,
input reset,
input clk
);
always @(posedge clk or posedge reset) begin
if(reset) test_interface.some_byte = 8'b1010_1010;
end
endmodule
module pass_through(
my_interface test_interface,
output logic byte_out
);
assign byte_out = test_interface.some_byte;
endmodule
Result: it recognizes the power-up condition! So it looks like I can trick Quartus into working around what appears to be a bug if I just add a never-asserted reset to all the modules where I have initial blocks and want to use interfaces.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, going back to the Quartus complaint about no source for the signal, your simplistic example probably just needs ANY driver, reset or otherwise. i.e. you don't need to add the fake reset, just the 'posedge clk' is enough.
See modified snippet below, which at least works the same in Modelsim and eliminates the Quartus warnings. Not sure if this is a better fit for your existing actual code base. I'm not sure why the struct vs. interface is apparently receiving different treatment within Quartus; you may need to file a service request to find out. Good luck.
interface my_interface;
logic some_byte;
initial some_byte = 8'b1010_1010;
endinterface
module fpga_tester(
input wire clk,
output logic test_byte
);
my_interface test_interface();
always @(posedge clk)
begin
test_interface.some_byte = test_interface.some_byte + 1'b1;
end
assign test_byte = test_interface.some_byte;
endmodule
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Well, going back to the Quartus complaint about no source for the signal, your simplistic example probably just needs ANY driver, reset or otherwise. i.e. you don't need to add the fake reset, just the 'posedge clk' is enough. See modified snippet below, which at least works the same in Modelsim and eliminates the Quartus warnings. Not sure if this is a better fit for your existing actual code base. --- Quote End --- I had to add the fake reset to get the register to come up in the 10101010 state. Without adding a reset (even if the reset is hard-wired to never assert!), Quartus will not recognize that I want a nonzero power-up state. Adding a clock alone did not help me. I see different behavior between ModelSim and Quartus when using the snippet of code from your message. In ModelSim the counter starts at 8'b1010_1010, but in Quartus it starts at 8'b0000_0000. That's the type of situation that caused my original problem. I will file a service request about the bug with initial statements for registers in interfaces.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It will be interesting to hear what they say.
I spent probably way to much time looking at it, but best I can tell, yes it looks like Quartus is strictly treating the instantiation in your top level module as a bundle of wires. If you go down with one or more submodules which reference that instance in their port list, then those submodules can use an 'initial' statement on the interface member and it works like you expect. The treatment seems similar to how you would have connected submodules with wires in the top level and output registers in the submodule port declarations, which maybe is how the tool author assumed it would be used. e.g. this works
interface my_interface;
logic some_byte;
function void tick;
some_byte = some_byte + 1'b1;
endfunction
function void init;
some_byte = 8'b1010_1010;
endfunction
endinterface
module fpga_tester(
input wire clk,
output logic test_byte
);
my_interface test_interface();
counter u0
(
.clk ( clk ),
.x (test_interface)
);
assign test_byte = test_interface.some_byte;
endmodule
module counter
(
input wire clk,
my_interface x
);
initial
x.init();
always @(posedge clk)
x.tick();
endmodule
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm the same user writing from a different account. Thank you for putting time into this. It gets a little clearer to me with each new experiment. Your code worked for me, and it led me to realize that Quartus isn't necessarily confused by initial blocks with interfaces. The issue seems to be about the combination of initial blocks specifically with interfaces that don't synthesize into clocked logic. Going back to my first post example, ModelSim and Quartus match in behavior if one simple change is made:
interface my_interface;
logic some_byte;
endinterface
module fpga_test(
input wire clk,
output logic test_byte
);
my_interface test_interface();
assign test_byte = test_interface.some_byte;
initial test_interface.some_byte = 8'b1010_1010;
always @(posedge clk) test_interface.some_byte <= test_interface.some_byte + 1'd1; //Adding clocked logic here
endmodule
That seems to be starting with test_byte equal to 8'b1010_1010 across platforms. Note that the caveat of requiring clocked behavior was not necessary when using a struct. That makes this still seem like a bug, but I can see how it is an arguable corner case. So the summary of the whole situation seems like this: -I added interfaces to working code to simplify it. -The code behavior no longer matched between ModelSim and Quartus. -The difference appeared to be due to registers initializing differently after adding interfaces. -I made a simple test case of an interface with an initial statement and found different behavior between ModelSim and Quartus. -The test case was *too* simple, and as a result brought up a small bug in Quartus. -I mistook the small bug for being the source of worse headaches than it actually is. It also seems to be important to note that even with the clocked logic, if I move the initial block inside the interface then it does not work. ModelSim sees the initialization, but Quartus does not. Here's that version for reference: interface my_interface;
logic some_byte;
initial some_byte = 8'b1010_1010;
endinterface
module fpga_test(
input wire clk,
output logic test_byte
);
my_interface test_interface();
assign test_byte = test_interface.some_byte;
always @(posedge clk) test_interface.some_byte <= test_interface.some_byte + 1'd1;
endmodule
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Try using mod ports. Just like modules you need ports or modports to drive or source from the registers inside the interface block. I think the simulator allows you to reference a logic type with hierarchical reference but not sure of Quartus.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have not been using modports because the latest version of Quartus (13.1) says it does not support them:
http://quartushelp.altera.com/current/mergedprojects/hdl/vlog/vlog_list_sys_vlog.htm (http://quartushelp.altera.com/current/mergedprojects/hdl/vlog/vlog_list_sys_vlog.htm) "25.5 - Modports - Not supported"- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That's funny because I remember seeing that its supported in earlier versions of the help file. In anycase I am using v13.1 and they are supported. Can any of Altera folks jump in here and confirm if this is not an errata in the documentation? Is the support for modports are indeed going to be deprecated?
Thank you. Best regards, Sanjay
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page