03-07-2019 06:41 AM
I am trying to synthesize a memory accessed by two clock threads (I am using SystemC). One clock thread (input_cthread) writes on the memory and the other one (run_cthread) reads from it.
Vivado HLS generates a 1 single port RAM with some control logic to access it of the style:
inbuff_address0_assign_proc : process(grp_mytop_input_cthread_fu_136_inbuff_address0, grp_mytop_input_cthread_fu_136_inbuff_ce0, grp_mytop_run_cthread_fu_168_inbuff_address0, grp_mytop_run_cthread_fu_168_inbuff_ce0) begin if ((ap_const_logic_1 = grp_mytop_run_cthread_fu_168_inbuff_ce0)) then inbuff_address0 <= grp_mytop_run_cthread_fu_168_inbuff_address0; elsif ((ap_const_logic_1 = grp_mytop_input_cthread_fu_136_inbuff_ce0)) then inbuff_address0 <= grp_mytop_input_cthread_fu_136_inbuff_address0; else inbuff_address0 <= "XXXX"; end if; end process; inbuff_ce0_assign_proc : process(grp_mytop_input_cthread_fu_136_inbuff_ce0, grp_mytop_run_cthread_fu_168_inbuff_ce0) begin if ((ap_const_logic_1 = grp_mytop_run_cthread_fu_168_inbuff_ce0)) then inbuff_ce0 <= grp_mytop_run_cthread_fu_168_inbuff_ce0; elsif ((ap_const_logic_1 = grp_mytop_input_cthread_fu_136_inbuff_ce0)) then inbuff_ce0 <= grp_mytop_input_cthread_fu_136_inbuff_ce0; else inbuff_ce0 <= 'X'; end if; end process;
(1) With a 2 port RAM it would be easier. I use to thought that Vivado HLS by default try to use 2 port RAM, or at least it can synthesized it when needed without needing to force it with a pragma. Nevertheless, 1 port RAM may be acceptable for this case.
(2) The structure if - elsif for assigning the addresses and clock enables is correct since it will prevent simultaneous access from the two clock threads. I have try to prevent it with control signals but this make it even more safer.
(3) But, Why it assigns 'X' values when both clock enables coming from the two cthreads are '1'? As far as I know 'X' mean impossible to know the value, and it is used when the simulator cannot compute the value (e.g. two different drivers are trying to put two incompatible values on a signal like '1' and '0'). It would be more reasonable to use the value '-' instead, that means "don't care", giving the chance to the RTL synthesis tool to choose the most convenient value.
Seeing 'X' values on the RTL simulation driven me crazy looking for errors when it turned out to be put them explicitly by the HLS tool.
By the way, the example project sc_RAM_port do not pass the C/RTL cosimulation. I needed to do the following modifications to get some results from it:
-First, increment the "end_time" value from 1100 to around 5000 clock cycles; because the synthesized RTL code needs more clock cycles to be executed.
-Add "handshake" signals to wait for the tasks to be completed before other dependent ones can start. I.e. wait for the initialization of the din memory finish before reading it, and waiting for the dout be writed before reading it. Because these tasks do not take 1 clock cycle any more after synthesis. And correct the Proc1 behavior to avoid it to continuously writing share_mem again and again (which avoids share_mem to be read).
Still, the C/RTL cosimulation do not pass because the testbench cannot read correct values from the dout memory. Although, the RTL signals on the Wave Viewer looks like correct.
Note: I am using Vivado HLS 2017.2
03-07-2019 07:27 AM
If I understand the core of your question... 'why use X instead of -'...
X by definition is that the value is unknown (indeterminate)... In your simulation, you really don't want to see those, when you are actually doing a read, as it means you have a indeterminate case. (e.g. a runtime, the 'X' (or '-') won't flow, if will just be a high and lows.
As for the -, which is don't care... this may be more appropriate for signals you intend to not look at. (e.g. you are only using 5 of 8 bits, so top 3 might be - don't care).
Either way, at runtime, you want to handle these things, so being 'visble' during simulation is to your benefit.
Hope that Helps
If so, Please mark as solution accepted. Kudos also welcomed. :-)
03-07-2019 08:51 AM
Thanks for your quick answer. I understand, that for data it uses the 'X' value when this data is not in use (i.e. do not read by anyone). It will not be a problem. That is the case of the address signal. Although, I still think it would be more appropiate the '-' don't care value, as you said, this is the case of signals you have not intent to look at them (at least at the current clock cycle).
However, I am seeing these 'X' values on control signals. In this particular example, on the clock enable (ce) signals (I have also seen these 'X' values on validation signals *_ap_vld). That is a problem because, precisely, these signals are which decide what other signals are in use (i.e. being read). I guess that I shall assume they are de-activating whatever they are controlling when they have a value of 'X'. But it would be more clear if they value '0'. Besides, it makes debuging more difficult, because when a 'X' value is seen on the control signal, it is not clear if it is due to this reason or due to an error.