Configure clock signal for black box in Simulink/System Generator - simulink

I use code VHDL to make a one-shot timer in Simulink by "black box" of System Generator. The module concludes input is: clk, en, trigger, delay & output is: pluse. Now I want to use System Generator to implement on Zynq 7020 and use clock frequency = 1.562Mhz. I read "ug897-vivado-system generator-user", but i still dont know how to configure clk.
The diagram in Matlab/Simulink
The VHDL code for one-shot timer/black box
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.VComponents.all;
entity oneshot is
port ( clk : in STD_LOGIC;
ce : in STD_LOGIC;
trigger : in STD_LOGIC:='0';
delay : in STD_LOGIC_VECTOR (7 downto 0);
pulse : out STD_LOGIC :='0');
end oneshot;
architecture Behavioral of oneshot is
signal count: INTEGER range 0 to 255; -- count variable
signal bus_rising_edge : boolean;
signal input_sync : std_logic_vector(0 to 2);
begin
input_syncronizer : process(clk) begin
if rising_edge(clk) then
input_sync <= to_x01(trigger)&input_sync(0 to 1);
end if;
end process ;
bus_rising_edge <= input_sync(0 to 1) = "10";
trigger_process: process (clk)
begin
-- wait for trigger leading edge
if rising_edge(clk) then
if bus_rising_edge then
pulse <= '1';
count <= to_integer(unsigned(delay));
elsif count > 1 then
pulse <= '1';
count <= count - 1;
else
pulse <= '0';
end if;
end if;
end process;
end Behavioral;
The Matlab code automatically create when importing VHDL code
https://drive.google.com/open?id=1jfztL-NgftDc7VAgAX4eHfuJF8uOgK3V
(sorry i cant post my code properly)

You can double click on system generator mark and select the clocking tab and change the period of your clock. this clock is use for simulation. in real, your operation clock is one you have on your board.

Related

Failure to handle clock inference in Dymola

The following model in Dymola gives an error,
model Test1
Real outvar;
Real outvarc;
Real internal;
parameter Real Tp=0.1;
equation
when Clock(Tp) then
internal = time;
end when;
outvar = hold(outvarc);
algorithm
if (firstTick(internal)) then
outvarc := 1;
else
outvarc := previous(outvarc);
outvarc := outvarc + 1;
end if;
end Test1;
If I modify the variable internal as follows then the model works.
model Test2
Real outvar;
Real outvarc;
Boolean internal(start=true);
parameter Real Tp=0.1;
equation
when Clock(Tp) then
internal = false;
end when;
outvar = hold(outvarc);
algorithm
if (firstTick(internal)) then
outvarc := 1;
else
outvarc := previous(outvarc);
outvarc := outvarc + 1;
end if;
end Test2;
Is there any explanation why model Test1 is giving an error?
It fails in Dymola 2022x and earlier.
In Dymola 2023 and later it gives the warning:
The sub clock, BaseClock_0.SubClock_1, includes pre, time, or
non-clocked when, but no solver method is specified. This is not
correct according to the specification and it could indicate that it
was clocked by mistake. The warning can be disabled by setting
Advanced.Translation.WarnForMissingSolverMethod=false;
That suggests that the simplest solution would be:
when Clock(Tp) then
internal = sample(time);
end when;
Basically time is not a clocked variable. (Yes, I'm aware that time in clocked partitions is messier than this suggests.)
Here is a suggestion for a little more compact code of the overall model. It gives a bit different results as it uses the "discrete time" internal to make equations discrete/clocked automatically, but I guess the would be the use-case anyways (otherwise sampling time does not make a lot of sense).
model Test3
parameter Real Tp=0.1;
discrete Real internal; // "discrete" is optional in Dymola, but helps understanding
discrete Real outvarc(start=1, fixed=true); // setting an initial value
Real outvar;
equation
internal = sample(time, Clock(Tp)); // sampling time with a locally defined clock and store it to "internal"
outvarc = previous(outvarc)+internal; // using a sampled/clocked variable (internal) makes the equation discrete
outvar = hold(outvarc); // converting to a continuous variable from a clocked one
end Test3;
Suggestions for further improvements welcome...

Dynamically switching connect in Modelica

Assume I have a large connector involving all kinds of base types (Real, Integer, String, Boolean). How can I switch connections based on state events?
I would like to do something like this:
model switch
input ComplicatedConnector icon[2];
output ComplicatedConnector ocon;
input Real x;
equation
if x >= 0 then
connect(ocon, icon[1]);
else
connect(ocon, icon[2]);
end if;
end switch;
This does not work. How can it be properly expressed in Modelica?
Answer based on comment by Adrian Pop.
model switch
input ComplicatedConnector icon[2];
output ComplicatedConnector ocon;
input Real x;
ComplicatedConnector con;
initial equation
con = icon[1];
equation
connect(ocon, con);
when x >= 0 then
con := icon[1];
end when;
when x < 0 then
con := icon[2];
end when;
end switch;
Update: The model above is wrong because ocon outputs the initial value of icon[1] forever if no event occurs which is not what you would expect from a switch. Note that this is not due to a wrong answer but due to my false interpretation of the answer. The following model is based on the answer by Michael Tiller.
model switch
input ComplicatedConnector icon[2];
output ComplicatedConnector ocon;
input Real x;
Integer k;
initial equation
k = 1;
equation
ocon = icon[k];
when x >= 0 then
k := 1;
elsewhen x < 0 then
k := 2;
end when;
end switch;
Is not possible. You can only switch them based on a parameter known at compile time (also known as structural parameter). The condition in the if equation containing connects needs to be a parameter expression.
Note that connect statements are equations. You can expand them out yourself. They exist mainly to avoid "bookkeeping" errors for generating boilerplate equations. So what I suggest you do is simply take your switch model and expand each connect into equations. The it should work.

Ones count system-verilog

I have a wire vector with 64 bits;
wire [63:0] sout;
I want to compute the sum of these bits or, equivalently, count the number of ones.
What is the best way to do this? (it should be synthesizable)
I prefer using for-loops as they are easier to scale and require less typing (and thereby less prone to typos).
SystemVerilog (IEEE Std 1800):
logic [$clog2($bits(sout)+1)-1:0] count_ones;
always_comb begin
count_ones = '0;
foreach(sout[idx]) begin
count_ones += sout[idx];
end
end
Verilog (IEEE Std 1364-2005):
parameter WIDTH = 64;
// NOTE: $clog2 was added in 1364-2005, not supported in 1364-1995 or 1364-2001
reg [$clog2(WIDTH+1)-1:0] count_ones;
integer idx;
always #* begin
count_ones = {WIDTH{1'b0}};
for( idx = 0; idx<WIDTH; idx = idx + 1) begin
count_ones = count_ones + sout[idx];
end
end
The $countones system function can be used. Refer to the IEEE Std 1800-2012, section "20.9 Bit vector system functions". It might not be synthesizable, but you did not list that as a requirement.
"Best" is rather subjective, but a simple and clear formulation would just be:
wire [6:0] sout_sum = sout[63] + sout[62] + ... + sout[1] + sout[0];
You might be able to think hard and come up with something that produces better synthesized results, but this is probably a good start until a timing tool says it's not good enough.
The following solution uses a function to calculate the total number of set (to High) bits in a 64-bits wide bus:
function logic [6:0] AddBitsOfBus (
input [63:0] InBus
);
AddBitsOfBus[2:0] = '0;
for (int k = 0; k < 64; k += 1) begin // for loop
AddBitsOfBus[6:0] += {6'b00_0000, InBus[k]};
end
endfunction
The following synthesizable SystemVerilog functions do this for you:
$countbits(sout,'1); // Counts the # of 1's
$countbits(sout,'0); // Counts the # of 0's
$countones(sout); // equivalent to $countbits(sout,'1)
The logic the synthesis tools will produce is a different story.
Ref: IEEE Std 1800-2012, Section 20.9

Implement FIR Filter in Verilog

I am trying to implement an FIR filter in Verilog. I have predetermined the coefficients in MATLAB. But I am not sure whether the registers will propagate properly with this code.
module fir_filter(
input clock,
input reset,
input wire[15:0] input_sample,
output reg[15:0] output_sample);
parameter N = 13;
reg signed[15:0] coeffs[12:0];
reg [15:0] holderBefore[12:0];
wire [15:0] toAdd[12:0];
always #(*)
begin
coeffs[0]=6375;
coeffs[1]=1;
coeffs[2]=-3656;
coeffs[3]=3;
coeffs[4]=4171;
coeffs[5]=4;
coeffs[6]=28404;
coeffs[7]=4;
coeffs[8]=4171;
coeffs[9]=3;
coeffs[10]=-3656;
coeffs[11]=1;
coeffs[12]=6375;
end
genvar i;
generate
for (i=0; i<N; i=i+1)
begin: mult
multiplier mult1(
.dataa(coeffs[i]),
.datab(holderBefore[i]),
.result(toAdd[i]));
end
endgenerate
always #(posedge clock or posedge reset)
begin
if(reset)
begin
holderBefore[12] <= 0;
holderBefore[11] <= 0;
holderBefore[10] <= 0;
holderBefore[9] <= 0;
holderBefore[8] <= 0;
holderBefore[7] <= 0;
holderBefore[6] <= 0;
holderBefore[5] <= 0;
holderBefore[4] <= 0;
holderBefore[3] <= 0;
holderBefore[2] <= 0;
holderBefore[1] <= 0;
holderBefore[0] <= 0;
output_sample <= 0;
end
else
begin
holderBefore[12] <= holderBefore[11];
holderBefore[11] <= holderBefore[10];
holderBefore[10] <= holderBefore[9];
holderBefore[9] <= holderBefore[8];
holderBefore[8] <= holderBefore[7];
holderBefore[7] <= holderBefore[6];
holderBefore[6] <= holderBefore[5];
holderBefore[5] <= holderBefore[4];
holderBefore[4] <= holderBefore[3];
holderBefore[3] <= holderBefore[2];
holderBefore[2] <= holderBefore[1];
holderBefore[1] <= holderBefore[0];
holderBefore[0] <= input_sample;
output_sample <= (input_sample + toAdd[0] + toAdd[1] +
toAdd[2] + toAdd[3] + toAdd[4] + toAdd[5] +
toAdd[6] + toAdd[7] + toAdd[8] + toAdd[9] +
toAdd[10] + toAdd[11] + toAdd[12]);
end
end
endmodule
Is this the best way to implement this? is there a better way to do the addition?
Any help is greatly appreciated!
Also resources that would help are also greatly appreciated.
Area and power efficient FIR/IIR filters are the holy grail for some.
Using generate statements you have instantiated 13 multipliers. Multipliers take up quite a lot of area. It is common to only instantiate one and time multiplex it (TDM). In this case supply a clock (tick) 13 times faster than the required output rate.
Your adder chain while looking valid again is going to be very big and could lead to timing problems as there could be very long ripple chains. Breaking this down over multiple cycles might result in lower area and power.
If you combine the multiplication of a sample with the addition you will have a more typical MAC architecture (Multiply Accumulate).
I would also avoid initialising constants in an always #* as no right hand sides of arguments change this may not trigger the sensitivity list.
For these I would use localparams, or if going down the TDM route I would create a Look up table (LUT).
always #* begin
case( program_counter )
0 : coeff = 6375;
1 : coeff = 1 ;
...
endcase
end
Assuming your choice of filter response is justified (5.2dB ripple!)
Then an approach is to tradeoff some response accuracy for reduced chip resources by using Canonical signed digit representation [http://en.wikipedia.org/wiki/Canonical_signed_digit] to approximate each coefficient. This Strength reduction [http://en.wikipedia.org/wiki/Strength_reduction] (compiler term) allows efficient shifts ie routing and adds to be used instead of expensive multiplies.
Then due to the symmetry of the coefficients the respective samples can be summed before applying the coefficient, which significantly drops the required chip resources.[1]
But then there is likely to be common factors in the coefficients implemented, which for a chip target may get some optimisation but for firmware significant improvements can be made.
[1] = DSP Tricks: An odd way to build a simplified FIR filter structure Richard G. Lyons
try http://www.embedded.com/design/embedded/4008837/DSP-Tricks-An-odd-way-to-build-a-simplified-FIR-filter-structure

Sample function doesn't work on Dymola

I try to compile the following code with Dymola:
class abc
import Modelica.SIunits;
parameter SIunits.Time delta_t=0.5;
constant Real a[:]={4,2,6,-1,3,5,7,4,-3,-6};
Real x;
Integer j(start=1);
Integer k=size(a, 1);
algorithm
when {(sample(0, delta_t) and j < k),j == 1} then
x := a[j];
j := j + 1;
end when;
end abc;
and for time = 0 the variable j starts with 2. But it should start with j = 1.
Does anybody have an idea for this problem?
Keep in mind that sample(x,y) means that sample is true at x+i*y where i starts at zero. Which is to say that sample(0, ...) becomes true at time=0.
Since j starts at 1 and k is presumably more than 1, it doesn't seem unexpected to me that sample(0, delta_t) and j<k should become true at the start of the simulation.
I suspect what you want is:
class abc
import Modelica.SIunits;
parameter SIunits.Time delta_t=0.5;
constant Real a[:]={4,2,6,-1,3,5,7,4,-3,-6};
Real x;
Integer j(start=1);
Integer k=size(a, 1);
algorithm
when {(sample(delta_t, delta_t) and j < k),j == 1} then
x := a[pre(j)];
j := pre(j) + 1;
end when;
end abc;
I don't really see the point of the j==1 condition. It is true at the outset which means it doesn't "become" true then. And since j is never decremented, I don't see why it should ever return to the value 1 once it increments for the first time.
Note that I added a pre around the right-hand side values for j. If this were in an
equation section, I'm pretty sure the pre would be required. Since it is an algorithm section, it is mainly to document the intent of the code. It also makes the code robust to switching from equation to algorithm section.
Of course, there is an event at time = 0 triggered by the expression sample(0, delta_t) and j<k which becomes true.
But in older versions of Dymola there is an bug with the initialization of discrete variables. For instance even if you remove sample(0.0, delta_t) and j<k in dymola74, j will become 2 at time=0. The issue was that the pre values of when clauses, where not initialized correct. As far as I know this is corrected at least in the version FD1 2013.