- Schmerm
- Sep 1, 2000
-
-
College Slice
|
CompEng PhD student checking in here. I think I might start on a project to add SystemVerilog support to the open source VTR (Verilog-to-Routing) toolchain. Yay! I may need to implement some new CAD algorithms, and want to push some of my own SV designs through it as benchmarks, without having to dumb down and convert it all to Verilog 1995 (the port naming syntax is so goddamn arcane...ugh)
|
#
¿
Sep 21, 2012 08:07
|
|
- Adbot
-
ADBOT LOVES YOU
|
|
#
¿
May 18, 2024 15:05
|
|
- Schmerm
- Sep 1, 2000
-
-
College Slice
|
Question for the FPGA guys. How many of you make use of dynamic timing analysis in your designs (post fitting timing simulations)? Or do you mostly get away with only static analysis? I'm referring specifically to designs with multiple time domains.
Speaking as an Altera user, I trust the synchronization primitives (the dcfifo and the altera standard synchronizer whose name I forget) for moving data between clock domains safely. Then, only static timing analysis post-fitting is needed. The STA tool also does metastability analysis and it usually gives MTBFs in the billions of years.
|
#
¿
Jul 8, 2013 17:34
|
|
- Schmerm
- Sep 1, 2000
-
-
College Slice
|
Best practices for synthesis question:
I have a statemachine that walks through states doing it's thing. This is great, but one of the states needs to do the same thing for 8 clocks. The Xilinx example Moore statemachine relies on three processes for running, a single process that assigns state <= next_state, a process that changes outputs based on the current value of state, and another process that determines the next_state from the current state plus inputs. This is great, but I'm not sure the easiest and cleanest way to get it to stay in a single state for a number of clocks (effectively for a certain amount of time). I have a few ways to do this in simulation, but I'm not sure which solution is more common and easier for the synthesis tool to make sense of.
1: Create a hardware counter. I did this with a shift register - when you enter the state, it starts shifting '1', and when the '1' pops out the other side, transitions. The implementation is in a separate vhdl file and is literally a std_logic_vector whose length is set as a generic parameter. This works, but seems like it ties the synthesis tools hands a bit by being specific.
2: Use a variable to control timing. The process for determining next state has a synchronous section that increments the variable and once it hits a certain amount, moves to the next state. I am hesitant to use variables because I do not have a good feeling for what hardware they turn into, but this is a pretty clean way to do it code-wise.
3: Add additional states. This seems kind of grotesque but I could simply have a bunch of states do_work_0 through do_work_7 instead of trying to sit in state do_work for 8 clocks. No counting necessary, it just walks through the states. However, I have a state machine with 12 states already, and this would balloon it up to 40 or so.
4: Additional state machine. I could build another state machine that just walks through eight states and use its outputs to control the main state machine. Seems similar to #2 in every way but implementation, to be honest. And if you have one-hot encoding, I suspect it will look very similar post synthesis.
I'm getting comfortable with VHDL, but I still have a huge black hole in my library of "design patterns" and I am still uncomfortable with the synthesis tool; I write code that will pass simulation no problem but I don't have a intuitive sense of what happens when I pass it down the toolchain.
I am one big case of analysis paralysis
Ew, VHDL. Aside from that, option 1 is essentially what I use whenever this needs to be done. Don't do #2 because it might break the synthesis tool's recognition of the state machine, since the logic will no longer be an unconditional "every clock, copy nextstate to state". 3 and 4 are identical but messy. #1, if done using a one-hot counter (= shift register) will be just as efficient as whatever state machines get synthesized as these days.
|
#
¿
Jul 11, 2013 19:19
|
|
- Schmerm
- Sep 1, 2000
-
-
College Slice
|
So can someone sensibly explain why I need to declare the output of a multiplexer or the like as a reg even though both I and the compiler know the resulting logic will not be registered? Obviously it's because you're using an always block. But if I use all blocking assignments and ensure that the output is defined in all 'execution paths' then there won't be a register created.
It seems like it would make more sense to let me declare the output as a wire, and then have the compiler generate an error if I didn't meet the requirements of it being purely combinatorial. That way at least I know what's happening and if I messed up. As is it just silently gets turned into a real register, I guess?
The left hand side of any assignment in an always block must be a 'reg', which you already said. If it's a combinational always block, it will generate a wire. If it's a clocked always block, it will generate a register. That's it. Blocking/nonblocking/executionpaths discussion is irrelevant, except for creating latches. Latches are bad and we don't talk about them in FPGA Land.
Switch to SystemVerilog if you can. There's a datatype called 'logic' that's usable in both always blocks and with assign statements, and can replace 'reg' and 'wire' for 99% of cases. There's also 'always_ff' and 'always_comb' blocks. The former ensures that you create nothing but registers (and errors will be generated if your flow creates latches). The latter is a nice syntactic replacement for 'always @*'
|
#
¿
Aug 29, 2013 21:41
|
|
- Schmerm
- Sep 1, 2000
-
-
College Slice
|
Verilog has had generate statements since Verilog-2001, and sensitivity lists are deprecated for anything other than maybe speeding up simulations.
|
#
¿
Aug 31, 2013 18:55
|
|
- Schmerm
- Sep 1, 2000
-
-
College Slice
|
Jesus guys, that sounds bad. Just go Altera already... synthesis works, and you get SystemVerilog support for all families, not just newer ones like with Xilinx.
Here's my conventions I use in (System)Verilog:
- All names lowercase
- Module inputs and outputs: i_inputname, o_outputname
- Exception to above, for topmost pins connecting to outside the FPGA, are all uppercase
- Clocks, especially: clk if there's one, or clk_300 for a/The 300MHz clock, clk_ddr for the memory clock, etc
- Active-low signals: suffix of _n
- States: Defined using 'localparam' in V2001, 'enum int unsigned' in SV, named S_IDLE, S_KILL_ALL_HUMANS, etc
- Control signals for a register 'foo' that is meant for holding things:
- foo_load - loading from a hardwired or selectable input
- foo_din - the input to load from, if applicable
- Control signals for a register 'foo' used as a counter:
- foo_inc - increment
- foo_dec - decrement
- foo_last - combinational signal to show that foo has reached its last value this cycle. Usually written as "wire foo_last = foo == 99" or "wire foo_last = foo == 0"
- foo_done - same as above, but for one-past-the-end semantics (like C-style for loops). "wire foo_done = foo == 100"
- Pipeline registers: foo_0, foo_1, etc for stage 0, stage 1, etc.
- Handshaking signals: valid/ready. Usually they're ports, so there is an i_valid, o_ready pair for receiving, and a o_valid, i_ready pair for sending
|
#
¿
Oct 27, 2013 23:07
|
|
- Adbot
-
ADBOT LOVES YOU
|
|
#
¿
May 18, 2024 15:05
|
|
- Schmerm
- Sep 1, 2000
-
-
College Slice
|
Could you simply infer a ROM from VHDL/Verilog? Both Xilinx and Altera support this for synthesis, and you can use the $readmemh Verilog system function to initialize the ROM contents from a file.
Altera: http://www.altera.com/literature/hb/qts/qts_qii51007.pdf p38
Xilinx XST (probably works in Vivado too): http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_1/xst.pdf p192
|
#
¿
Nov 4, 2013 02:50
|
|