I have the following input: logic SWI[7: 0], which I would like to control from another executable, in C ++ for example.
And I have the following outputs: logic LED[7:0], SEG[7: 0], which I would like to get in real time.
Is there any way to simulate systemverilog in such a way that I can simulate inputs and get outputs (in this model)?
Example code that I would like to run:
logic T1, T2;
always_comb begin
T1 <= SWI[0];
T2 <= SWI[1];
LED[0] <= T1 && T2;
end
I'm sorry for bad english.
You can use DPI (C/C++ code linked to the simulation) to get/set values of Verilog signals. Then you can implement some IPC from this DPI code to another executable (e.g. using sockets, pipes etc.).
Related
How could you determine the number of instances of a given class within this model at translation. This size is to be used to set the size of a vector.
model ModelToBeCounted
end ModelToBeCounted;
model Example
ModelToBeCounted A;
ModelToBeCounted B;
ModelToBeCounted C;
end Example;
So in this example I would like to like to determine the number instances of ModelToBeCounted. These instances could also be within instances of other classes. The code at the top level could be altered to do this and the ModelToBeCounted could also be altered.
I tried using external objects however I could not find a way to ensure that the external objects are all created before the function used to report the total number of external objects was run.
Any ideas?
Thanks
If you can modify the model ModelToBeCounted you can do this using inner/outer:
connector C
Real totalNum;
flow Real addNum;
end C;
model InnerObjectCounter
C c;
equation
c.totalNum+c.addNum=0 "Correct sign";
annotation(missingInnerMessage="Add inner component to count objects");
end InnerObjectCounter;
model FlowSource
C c;
equation
c.addNum=1;
end FlowSource;
model AddCounter
outer InnerObjectCounter objectCounter;
final Integer totalNum=integer(flowSource.c.totalNum);
FlowSource flowSource;
equation
connect(flowSource.c, objectCounter.c);
end AddCounter;
model ModelToBeCounted
AddCounter c;
end ModelToBeCounted;
All components are automatically connected to the inner object using inner/outer-mechanism, and they have a flow of 1 that is summed together.
If you cannot modify the model ModelToBeCounted, and you are willing to use non-standarized methods you can set the flag:
Hidden.AllowAutomaticInstanceOf=true;
and then use:
final parameter Integer m=sum(1 for m in P.ModelToBeCounted);
From:
https://github.com/modelica/ModelicaSpecification/blob/MCP/0021/RationaleMCP/0021/
The ModelManagement library can do that.
In fact, there is exactly what you need available as a function:
ModelManagement.Structure.Instantiated.CountUsedModels("Example", {"ModelToBeCounted"});
= {3}
The library is installed with Dymola and available with the standard license.
You just have to open it from the Libraries menu.
A problem could be, that this function has to translate your model. I am not sure how well this will work for your requirement:
This size is to be used to set the size of a vector.
I am currently developing an AES encryption core for a Pynq-Z1 FPGA board. I would like to see the routing of the logic in FPGA logic and timing summary of the design.
The project synthesises, but it results in a warning saying that I am using exceeding the number of IOB blocks on the package. This is understandable because the core takes in and outputs a 4 x 4 matrix.
Instead, I would like to have "internal I/O" in order to see the routing on FPGA fabric. How would I go about doing this? Currently, the device view shows an empty topology (shown below) but my synthesised design utilises 4148 LUT and 389 FF. I expect to see some CLBs highlighted.
design device view
I appreciate any feedback and reference to any application notes which might further progress my FPGA understanding.
Cheers
You can use a simple wrapper around your core with a serial interface. Something like:
entity wrapper is
port(clk, rst, dsi, dsi_core, shift_out: in std_ulogic;
di: in std_ulogic_vector(7 downto 0);
dso_core: out std_ulogic;
do: out std_ulogic_vector(7 downto 0)
);
end entity wrapper;
architecture rtl of wrapper is
signal di_core, do_core, do_buffer: std_ulogic_vector(127 downto 0);
begin
u0: entity work.core(rtl)
port map(clk, rst, dsi_core, di_core, dso_core, do_core);
input_process: process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
di_core <= (others => '0');
elsif dsi = '1' then
di_core <= di & di_core(127 downto 8);
end if;
end if;
end process input_process;
output_process: process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
do_buffer <= (others => '0');
elsif dso_core = '1' then
do_buffer <= do_core;
elsif shift_out = '1' then
do_buffer <= do_buffer(119 downto 0) & X"00";
end if;
end if;
end process output_process;
do <= do_buffer(127 downto 120);
end architecture rtl;
The wrapper just receives inputs, one byte at a time (when dsi = '1') and shifts them in a 128-bits register that is connected to the 128-bits input of your core. When 16 bytes have been entered the environment asserts dsi_core to instruct the core that the 128-bits input can be sampled and processed. The environment waits until the core asserts dso_core, signalling that the processing is over and the 128-bits output is available on the do_core output port of core. When dso_core is asserted the wrapper samples do_core in a 128-bits register (do_buffer). The environment can now read the leftmost byte of do_buffer which drives the do output port of the wrapper. The environment asserts shift_out to shift do_buffer one byte to the left and read the next byte...
This kind of wrapper is a very common practice when you want to test in the real hardware a sub-component of a larger system. As it frequently happens that the number of IOs of sub-components exceeds the number of available IOs, serial input-output solves this. Of course there is a significant latency overhead due to the IO operations but it is just for testing, isn't it?
Your demands are contradictory.
If the design can not place all the I/Os it can not show all the routing as it has not all the begin and/or endpoints. You should reduce your I/O.
The simplest way is to have a real or imaginary interface which much less pins.
An imaginary interface is one which is syntactically correct, reduces your I/Os but will never be used in real life so does not have to be functionally correct.
As it happens you are the third person to ask about reducing I/O in the last weeks and I posted an (untested) SPI interface which has a parameter to generate an arbitrary number of internal inputs and outputs. You can find it here: How can I assign a 256-bit std_logic_vector input
I have read the book "Digital Design and Computers Architecture" by David Harris and I have a question about SystemVerilog examples in this book. After the introduction in the "parameterized construction", which is # (parameter ...), this operator is used almost in every example.
For example, the "subtractor" module from this book:
module subtractor #(parameter N = 8)
(input logic [N - 1:0] a,b,
output logic [N - 1:0] y);
assign y = a - b;
endmodule
What's the reason of using N in this code?
Can't we just write the following?:
input logic [7:0] a,b,
output logic [7:0] y);
Moreover, such parameters are used in almost every example further in the book but, as for me, there is no reason for using it. We can set the number of bits directly in square brackets without using additional "parameters".
So, what is the reason of such form of coding above?
The use of parameters serves a number of purposes.
It is always a better programming practice to use a symbolic name associated with a value than using a literal value directly. DATA_WIDTH instead of N would have been a more appropriate example. This documents the meaning of the value.
When a change to that value is needed, you have a single place to make that change, and less chance that you'll miss a change, or change an unintended value.
The use of parameters allows you to re-use the same code in many different places by creating a template and then overriding the parameter values as needed.
If I have both alwas_comb and always_ff in a single module, which one executed first?.
for example, I have seen this code in a book but I am confused about the functionality. for example, if WE=0 what will be the value of Qout?
module SyncRAM #(parameter M = 4, N = 8)(output logic [N-1:0] Qout,
input logic [M-1:0] Address, input logic [N-1:0] Data, input logic clk, WE);
logic [N-1:0] mem [0:(1<<M)-1];
always_comb
Qout = mem[Address];
always_ff #(posedge clk)
if (~WE)
mem[Address] <= Data;
endmodule
Any help about the truth table of this code is appreciated,
regards
The specific answer to your question is that Qout will just track the value of mem[Address]. In other words, on the rising edge of the clock, if WE is 0, Qout will be driven with the value written to the memory. This is because the memory will behave like a bank of flip-flops, while the Qout output will behave as if it is directly connected to the Q output of a bank of flip-flops.
The order of the execution of the two always blocks is deterministic, because Qout is driven using a blocking assignment (=), whereas the memory is written to using a non-blocking assignment (<=). See the answer here for much more detail.
I am trying to mimic the behavior of MATLAB's Simulink relay block with just MATLAB code.
My code is as follows (not familiar with persistent variable? click) :
function out = fcn(u,delta)
persistent y;
if isempty(y)
y = 0;
end
if u >= delta
y = 1;
elseif u <= -delta
y = 0;
end
out = y;
When I look to the output and compare with the real relay block I see :
Where does the difference come from?
Both blocks insert the same sample time, does the relay block have something extra to show the discontinuity?
Simulink block diagram download
I'm not quite sure about this explanation, maybe somebody can support it.
The MATLAB function Block does not support Zero-Crossing Detection, the Relay Block does. That means the latter knows in advance, when your sine will reach the threshold delta and sets the output accordingly to the correct time. The MATLAB function Block needs 2 or more steps to detect the slope (respectively the crossing of the threshold). So from one step to another it realizes that the condition for the new output was set and updates the output and you get a ramp, not a step.
C/C++ S-Functions do have Zero-Crossing Detection - though it seems quite complicated.