Background and clarifications:
I've never developed/written a single piece of hardware before, but I'm currently using Verilog to develop a huge project for a FPGA as my final graduation project.
I've got some questions on how to write verilog code efficiently. (Assume that, when I say "efficient", I mean "the way that uses less area and pins of the board").
Within the problems I'll suggest possible solutions, but, if none of them is right, feel free to negate them and add your correct solution.
In a certain way, problem 1 is the same as problem 3, so feel free to answer only one of them. I've written both to provide another example of the problem, just in case one feels more comfortable in answering one than the other.
In case you don't know how to answer problem 2, don't worry, as it's not the main problem here.
Thank you for your help.
Problems:
1 - Let's assume we have a module X that controls if modules A, B, ... N are logically on/off, that is, it sends signals to them to signal if they should be enabled or disabled. I see two ways of doing this:
Option 1: Send, to each destination module, a pair of enable/disable wires, wasting space with wires. i.e.:
module X(o_enable1, o_enable2, o_disable1, o_disable2);
assign i_enable1 = o_enable1;
assign i_disable1 = o_disable1;
module A(i_enable1, i_disable1);
assign i_enable2 = o_enable2;
assign i_disable2 = o_disable2;
module B(i_enable2, i_disable2);
Option 2: Create a bus, and each destination module would be responsible to mask it and verify if the enable/disable signal was sent to it, saving wire space, but creating a demux for every module. i.e.:
// o_enableDisable -> 0 = `ENABLE, 1 = `DISABLE
module X(o_enableDisable, o_enableDisable_bus);
assign i_enDis1 = o_enableDisable;
assign i_enDis_bus1 = o_enableDisable;
module A(i_enDis1, i_enDis_bus1);
assign i_enDis2 = o_enableDisable2;
assign i_enDis_bus2 = o_enableDisable2;
module B(i_enDis2, i_enDis_bus2);
// ... Inside A
if ((if i_enDis1 == `ENABLE)&&(i_enDis_bus1 == ENABLE_FOO1)) // Do something
if ((if i_enDis1 == `DISABLE)&&(i_enDis_bus1 == DISABLE_FOO1)) // Do something
2 - In the previous problem, we assumed that we were going to enable/disable modules logically. In case we wanted to turn them on/off physically to save power, is there a way to do that, or do we just have an if statement inside the module? i.e:
if (enabled) begin
// Contents of module while on
end else begin
// Contents of module while off
end
3 - Let's assume we have a decoder module X that sends commands to modules A, B, ..., N. I see 3 ways to do this:
Option 1: Commands as single wires, loosing pins, but saving the space of a demux. i.e.:
module X(o_com1, ..., o_com_m, ..., o_com_n);
assign i_com1 = o_com1;
// ...
assign i_com_m = o_com_m;
module A(i_com1, ... , i_com_m);
module B(i_com_m_plus_1, ..., i_com_n);
Option 2: Logarithmic input to be decoded inside destination module, wasting space with a demux. (Note that X decodes an instruction, decides which module it should send a command to and then sends a command to it)
module X(o_command_A, o_command_B, ...);
assign i_command_A = o_command_A;
module A(i_command_A);
assign i_command_B = o_command_B;
module B(i_command_B);
// Inside A
case (i_command_A)
`COMMAND_1: begin /* ... */ end
// ...
`COMMAND_n: begin /* ... */end
endcase
Option 3: A mix of both.
-
\$\begingroup\$ Maybe you can also think about AND-ing specific outputs of each module with an ENABLE/DISABLE line. Almost the same as option 1, but you can tactically choose which outputs (and/or inputs) you want to mask. \$\endgroup\$Evert– Evert2014年10月14日 14:57:30 +00:00Commented Oct 14, 2014 at 14:57
-
\$\begingroup\$ @Evert, the problem with that solution is that the module would, depending on the contents of it's idle state, operate, possibly consuming more energy than it should. \$\endgroup\$Daniel Carvalho– Daniel Carvalho2014年10月14日 16:44:16 +00:00Commented Oct 14, 2014 at 16:44
2 Answers 2
First, when designing FPGA's we mostly just think about "resources" rather than "space". Resources are things like routing resources, logic cells, RAM blocks, multiply-add blocks, etc. It looks like you're concerned about minimizing the use of routing resources, and willing to use more logic cells to do that.
Really, the best way to answer your questions (and first off, to find out if trading logic for routing is the right thing to do) is to synthesize your first-draft design and look at the resource usage. If routing resources are close to fully utilized, then start looking for ways to reduce them. If logic is close to fully utilized, then start looking for ways to make the opposite kind of optimization.
Let's assume we have a module X that controls if modules A, B, ... N are logically on/off, that is, it sends signals to them to signal if they should be enabled or disabled.
The typical way to do this in an FPGA is to just let all N modules run continuously. If only one out of the N are used at any given time, then you can often just use a mux to select which of the outputs gets used by downstream logic. If the combinations of modules being "disabled" is more complex, then you often just tell downstream logic to ignore those inputs, rather than disabling the module generating them.
You normally don't have separate wires for enable
and disable
like you proposed in your 1st option. Just one wire that is (for exampel) high when the module should be enabled and low when it should be disabled.
Although of course having separate enable
and disable
lines that only pulse intermittently is also possible if you have a good reason to do it. They would typically drive the SET and RESET inputs of a flip-flop to generate the actual enable
signal.
In the previous problem, we assumed that we were going to enable/disable modules logically. In case we wanted to turn them on/off physically to save power, is there a way to do that, or do we just have an if statement inside the module?
FPGAs don't typically have provisions to selectively power down parts of the fabric.
It is possible to use enable pins to reduce power consumption (due to reduced switching), but if the amount of logic being disabled is not a very large fraction of your design, it's not likely to significantly improve your power budget.
Also, you need to show that at any given time at least some known fraction of the logic is disabled, since you'll have to design your power supplies and heat sinking to account for the worst-case operating conditions anyway.
Let's assume we have a decoder module X that sends commands to modules A, B, ..., N. I see 3 ways to do this:
Your option 1 (a seperate signal for each command) is a very common FPGA coding style. Similarly, one-hot encoding is typically recommended by synthesis tool vendors for encoding state machine states.
-
\$\begingroup\$ I was planning to do a one-hot encoding on the enable/disable problem (At my current design, all modules run in parallel, but, if disabled, they just pass the input to the output), and have a flip flop for each one of the modules on the decoder, with a wire connecting them. Do you recommend this approach? Besides that, do you recommend any books/websites to learn about hardware coding techniques (I'm a C guy)? \$\endgroup\$Daniel Carvalho– Daniel Carvalho2014年10月14日 22:47:13 +00:00Commented Oct 14, 2014 at 22:47
-
\$\begingroup\$ @DanielCarvalho, I mostly learned from Xilinx application notes. Be sure to read the User Guide for your synthesis tool thoroughly. \$\endgroup\$The Photon– The Photon2014年10月14日 23:22:01 +00:00Commented Oct 14, 2014 at 23:22
-
\$\begingroup\$ For an example of the typical way to implement an ALU, for example, look here: edaboard.com/thread311433.html Basically, just do all the operations, then put a mux at the end to choose which one gets output. \$\endgroup\$The Photon– The Photon2014年10月14日 23:25:42 +00:00Commented Oct 14, 2014 at 23:25
The FPGA layout will not really care about your modules at all, but rather create one big conglomerate of gates and then try to find an optimal layout.
Enable signals in FPGAs are usually used only on the registers, which have a dedicated enable
input. If you disable a module by pulling its enable signal low, you are close to the lowest possible power consumption, as LUT outputs will no longer change, and thus gates connected to their outputs need not switch.
If you use two wires that go high for a state change, you need a flip-flop that combines them to a single logic level, and the optimizer would be stupid not to move that close to your controller component and only route a single enable line, so you can simply make this explicit. The same thing would probably happen to the bus architecture, but the optimizer would have to work harder for it and might be constrained from finding the optimal solution because of some corner case.
A common mistake is to switch the clock line with the enable signal. This is common in ASIC design, because it will conserve quite an amount of power, but in FPGAs, this does not really work because clock distribution is a separate network. FPGAs also do not have a programmable power distribution network, so there is no way to remove power from an area on the chip either. If you were to build an ASIC with that logic, you'd add these things. There is a good FOSDEM talk about this if you are interested.
For command multiplexing again it does not matter that much, because the optimizer will do its thing anyway. I'd keep it in the module, where it logically belongs.
-
\$\begingroup\$ OP should also be aware that RESET signals often have dedicated routing resources as well. This means that if you can use the same signal to reset as much of your logic as possible, you will avoid using general routing resources and also probably get better timing performance. \$\endgroup\$The Photon– The Photon2014年10月14日 16:16:31 +00:00Commented Oct 14, 2014 at 16:16
-
\$\begingroup\$ Simon, So I should apply the writability/readability law to my current/future designs? So far I think the single wires solution would be the best, as the compiler would be able to do its thing in an easier manner. About command multiplexing, wouldn't it belong to the decoder module, instead of the destination module? \$\endgroup\$Daniel Carvalho– Daniel Carvalho2014年10月14日 16:55:15 +00:00Commented Oct 14, 2014 at 16:55