Operating CORDIC IP VHDL - vhdl

I have been looking extensively into the operation of the CORDIC IP for use with Sin and Cos in VHDL.
According to page 24 of the CORDIC V6 documentation: https://www.xilinx.com/support/documentation/ip_documentation/cordic/v6_0/pg105-cordic.pdf#G6.297366 , the Sin and Cos functionality with the module should only require a PHASE_IN to provide data, and should return an X_OUT and a Y_OUT corresponding to the sin and cos of the PHASE_IN respectively. The generated IP diagram also shows an aclk, s_axis_cartesian_tvalid and s_axis_phase_tvalid input are required, and the module returns s_axis_phase_tready, m_axis_dout_tdata, and m_axis_dout_tvalid. Table 2-1 indicates that PHASE_IN is on the input s_axis_phase_tdata, and X_OUT and Y_OUT are on the channel m_axis_dout_tdata. I have followed the steps on page 35 of the designing with IP guide: https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_1/ug896-vivado-ip.pdf to generate an instantiation file which I have used to create a simple test bed.
However when I test a Sin Cos CORDIC IP while providing a constant aclk, setting the tvalid to high and proving a tdata of 0, I get nothing back from the module, even after waiting for a very large number of clock cycles (10000). I appear to get back undefined (U) values for both the s_axis_phase_tready and the m_axis_dout_tvalid along with a constant 0 from the m_axis_dout_tvalid, which seems to indicate something is wrong with my core instantiation, but I believe I have followed everything the documentation has provided.
I will promptly provide any new information if requested, but ultimately I'm wondering if I'm doing something wrong to utilize this IP?

I just found the solution to this problem, if anyone encounters this please check if this fix helps you.
The aclk seems to require an immediate delay before use, so ensure it stays at 0 for a whole clock cycle period before commencing cycles.
This is not mentioned in the text as far as I can tell, which made this issue very difficult to find.

Related

How to drive the DDS Compiler IP core from Xilinx

I completed Anton Potočniks' introductory guide to the red pitaya board and I am now able to send commands from the linux machine running on the SoC to its FPGA logic.
I would like to further modify the project so that I can control the phase of the signal that is being transmitted via the red pitayas' DAC. Some pins (from 7 down to 1) of the first GPIO port were still unused so I started setting them from within the OS and used the red pitaya's LEDs to confirm that they were being set without interfering with the functionality of Anton Potočnik's "high bandwidth averager".
I then set the DDS_compilers' to Phase Offset Programmability to "streaming" mode so that it can be configured on the fly using the bits that are currently controling the red pitaya's LEDs. I used some slices to connect my signals to the AXI4-Stream Constant IP core, which in turn drives the DDS compiler.
Unfortunately the DAC is just giving me a constant output of 500 mV.
I created a new project with a testbench for the DDS compiler, because synthesis takes a long time and doesn't give me much insight into what is happening.
Unfortunately all the output signals of the DDS compiler are undefined.
My question:
What am I doing wrong and how can I proceed to control DACs' phase?
EDIT1; here is my test bench
The IP core is configured as follows, so many of the control signals that I provided should not be required:
EDIT2; I changed declarations of the form m_axis_data_tready => '0' to m_axis_phase_tready => m_axis_phase_tready_signal. I also took a look at the wrapper file called dds_compiler_0.vhd and saw that it treats both m_axis_phase_tready and m_axis_data_tready as inputs.
My simulation results remained unchanged...
My new test bench can be found here.
EDIT3: Vivado was just giving me the old simulation results - creating a new testbench, deleting the file under <project_name>.sim/sim_1/behav/xsim/simulate.log and restarting vivado solved this problem.
I noticed that the wrapper file (dds_compiler_0.vhd) only has five ports:
aclk (in)
s_axis_phase_tvalid (in)
s_axis_phase_tdata (in)
m_axis_data_tvalid (out)
and m_axis_data_tdata (out)
So I removed all the unnecessary control signals and got a new simulation result, but I am still not recieving any useful output from the dds_compiler:
The corresponding testbench can be found here.
I also don't get any valid output when I include the control signals.
The corresponding testbench can be found here.
Looks like m_axis_data_tready is not connected. No data will come out unless that's asserted.

Proper way to change state on a state machine in VHDL

I'm working on a FPGA project where I need to read data from an image sensor. This sensor has different image modes (like test pattern, frame, binning, etc.) and in order to change image mode I need to look for specific signals before writing into the registers.
I have inherited some code that I need to fix since the image sensor sometimes gets stuck when we change image mode.
Concerning the change of image mode, a state machine is used.
The following piece of code shows how the registers for changing mode are currently written.
Essentially, when we want to change mode, we need to wait that the signal MODE_SIG_HIGH becomes high before writing into the registers. Then, when this condition happens, we check what mode we want to set. For example, to set set test pattern, we check if bit S2 is set. Then we performs all the operations to actually change mode (line 10).
01. ...
02. WHEN MODE_SIG_HIGH =>
03. NEXT_ST <= MODE_SIG_HIGH;
04. ...
05. IF S2 = '1' THEN
06. -- configure the sensor to
07. NEXT_ST <= CONFIGURE_TEST_PATTERN;
08. END IF;
09. ...
10. WHEN CONFIGURE_TEST_PATTERN =>
11. ...
I'm having a debate with a friend of mine concerning what is the best way to change state when a new event happens. The above solution doesn't seem right to me.
As far as I understood, when we enter a sate, all the instructions contained in that state are performed in parallel. Therefore, concerning the above piece of code, when we enter the state MODE_SIG_HIGH the instruction at line 03 is executed in parallel to the IF condition. My point is that if the bit S2 is set to 1, the IF condition is true and we end up assigning the value CONFIGURE_TEST_PATTERN to the NEXT_ST. An this ends up in assigning two different values to the same variable (in parallel), in line 03 and in line 07. Am I right or am I missing some basic behavior? The reason for having the instruction at line 3 is because after we enter MODE_SIG_HIGH, it could take some clock cycles before we see on of the mode bits set.
As far as I understood, when we enter a sate, all the instructions
contained in that state are performed in parallel.
Not quite. The only things in VHDL which are concurrent ('performed in parallel') are:
processes
concurrent signal assignments
component instantiations
concurrent procedure calls
concurrent assertions (inc.PSL)
generates
blocks
The code inside a process or subprogram (function/prodedure) executes sequentially. This is where you do your conventional programming, using sequential statements (ie. nothing in the list above). These are your standard control constructs (if, case, loop, etc), sequential signal assignments, and so on. If you carry out signal (or variable) assignments in a sequential region, the last one wins, just like a conventional programming language. There are scheduling rules that make this happen, but you don't need to know about those (yet!)

XILINX ISE set I/O Marker as Clock

I'm on Xilinx ISE IDE and using the Schematic Editor.
(click for new window)
The constraints file is following:
NET "A" LOC = M18;
NET "F" LOC = P15;
NET "B" LOC = M16;
NET "A" PULLUP;
NET "B" PULLUP;
NET "F" DRIVE = 8;
But when I want to compile my program, there is this error:
ERROR:Place:1108 - A clock IOB / BUFGMUX clock component pair have been found
that are not placed at an optimal clock IOB / BUFGMUX site pair. The clock
IOB component <B> is placed at site <M16>. The corresponding BUFG component
<B_BUFGP/BUFG> is placed at site <BUFGMUX_X2Y3>. There is only a select set
of IOBs that can use the fast path to the Clocker buffer, and they are not
being used. You may want to analyze why this problem exists and correct it.
If this sub optimal condition is acceptable for this design, you may use the
CLOCK_DEDICATED_ROUTE constraint in the .ucf file to demote this message to a
WARNING and allow your design to continue. However, the use of this override
is highly discouraged as it may lead to very poor timing results. It is
recommended that this error condition be corrected in the design. A list of
all the COMP.PINs used in this clock placement rule is listed below. These
examples can be used directly in the .ucf file to override this clock rule.
< NET "B" CLOCK_DEDICATED_ROUTE = FALSE; >
ERROR:Pack:1654 - The timing-driven placement phase encountered an error.
How to fix it?
While any signal can theoretically be used as a clock, it's not true for FPGA; at least not optimally. Clocks need special considerations that translate to restriction on which pin of the FPGA can be routed to the clock network.
I suspect that in your case, you used a push-button to act as a clock signal, which will only work on a very small design (like yours) because of debouncing and the fact that it's not a clock-enabled input port.
You can tell the tool that you want the sub-optimal and potentially erroneous clock path by adding the following constraint to your .ucf:
NET "B" CLOCK_DEDICATED_ROUTE = FALSE;
Keep in mind that you shouldn't do that without being sure that your design is fine with it... I recommend that you do further design with a "real" clock connected to a clock port on your FPGA, every board has one. That constraint will make your design work, but in a larger, faster design is likely to be a source of problems.

Specman-simulator synchronization issue?

I am using Cadence's Ethernet eVC wherein the agent's monitor is tapped at the following signals:
. ____________ _____
.clk _____| |__________________|
. ________ _______ ________________ _________
.data __0a____X___07__X_______0b_______X_________
. ^ ^
It samples data at the rising and falling edges of the clock. In the example above, the data 0x07 is garbage data, and the valid values are 0xa (clk rise) and 0xb (clk fall). However, the monitor is sampling (for clk fall) 0x7!
I'm suspecting this is a Specman-simulator synchronization issue. How can this be resolved if it is?
Simulator - IES 13.10
irun 13.10 options - (I'll include here only those which I think could be relevant to the issue, plus those which I've no idea yet what their purpose is)
-nomxindr
-vhdlsync
+neg_tchk
-nontcglitch
+transport_path_delays
-notimezeroasrtmsg
-pli_export
-snstubelab
Languages - VHDL (top testbench), Verilog (DUT), Specman (virtual sequence, Enet and OCP eVCs)
Time between 0x07 (left ^ in the waveform above) and falling edge of clock (right ^) = 0.098ns
One colleague suggested using -sntimescale, but I still can't imagine how that is causing/would resolve the issue. Any of these search strings were not showing helpful hints, even those articles from Cadence: "specman tick synchronization delta delay timescale precision"
This could be indeed an issue of timescale.
There is a comprehensive cookbook talking about deugging specman simulator interface synchronization issues. please take a look here.
To check what is the timescale used in your simulation, you can add -print_hdl_precision option to irun to print the precision for the VHDL hierarchy. For Verilog, it will be printed automatically in case it is set either in the code or via irun options. the information will be printed during elaboration.
To check the timescale used by Specman, you can issue the following command from Specman prompt:
SN> print get_timescale()
Another option to try (only after the timescale option doesn't help) is to remove the -vhdlsync flag. Indeed in most of the mixed environments you should add this flag. But there are rare cases in which the environment works better without it. If you try removing this flag, just remember to re-elaborate.
If you don't find the solution for your problem in the cookbook, deeper investigation should be done. for example, how does specman samples the signal. is it a simple_port, event_port, tick access, etc.. also some trace and probe commands could be helpful. In such case, I suggest to contact Cadence support.
Good Luck!
Semadar

Optimisation of RAM

I'm currently debugging my DPRAM. As usual, simulation works perfectly but in real life it fails. The syntax is as such:
ram[Address][Data]
I can get the data to write to the first 8 addresses but anymore and the data is just lost (even on chipscope). As a work around, I stitched two pieces of DPRAM together with a simple logical switch to re-route the data to the second DPRAM after it hit the eighth address. This worked but it just looks so messy.
My thinking is that it is being optimised away, even if it isn't this will be a good learning curve anyway (and any thoughts on this are welcome).
Here is the signal variable in the DPRAM with my effort at stopping it from being optimised away:
type ram_array is array(16 downto 0) of std_logic_vector(31 downto 0);
shared variable ram: ram_array;
attribute KEEP: string;
attribute KEEP of ram_array : type is "TRUE";
I think I need to add a line to the UCF file also though I can't seem to get the syntax right, with entity name path obviously changed:
NET "entity/name/path/dpram/ram_array" KEEP ="TRUE";
So is this how I'd add the code if I wanted to stop optimisation?
EDIT:
Output (guess there wasn't optimisation):
Found 17x32-bit dual-port RAM <Mram_ram> for signal <ram>. Summary: inferred 1 RAM(s). inferred 65 D-type flip-flop(s). Unit <dpram> synthesized.
Thanks =)
Don't use shared variable for synthesizable code
If your code needs to be synthesizable, then don't use shared variable.
Inferring BlockRAM
If you need sample code to implement your memory without using a shared variable, use the documentation provided for your FPGA.
Sample doc links :
(xilinx) http://www.xilinx.com/support/documentation/sw_manuals/xilinx12_2/xst_v6s6.pdf
(altera) http://www.altera.com/literature/hb/qts/qts_qii51007.pdf
Hope this helps.

Resources