how to update Real variable based on different scenarios in Modelica? - initialization

I built the model below in Modelica, the Kc and Ah are supposed to update for mode 3 and mode 4, but the simulation results show that Kc and Ah are always 1 and 0. Where does the error come from, how to update a Real variable in Modelica
model LiquidFraction_modify_Q
parameter Real Bh=2.118;
parameter Real Bc=18.37;
parameter Real Tmc=21.56+273.15;
parameter Real Tmh=22.32+273.15;
parameter Real vh=2.804;
parameter Real vc=31.11;
Real Ah;
Real Kc;
Real Kh=1;
Real Ac=0;
Boolean heating_pre;
Real mode;
initial equation
heating_pre=true;
Kc=1;
Ah=0;
equation
if heating_pre then //"previous heating mode"
if Tair>=Tpcm then
H=Ah+(Kh-Ah)/(1+exp(-Bh*(Tpcm-Tmh)))^(1/vh);
dHdT=-(Bh*exp(Bh*(Tmh-Tpcm))*(Ah-Kh))/(vh*(exp(Bh*(Tmh-Tpcm))+1)^(1/vh+1));
mode=1;
//"continue heating mode"
else
H=Ah+(Kh-Ah)/(1+exp(-Bh*(Tpcm-Tmh)))^(1/vh);
dHdT=-(Bh*exp(Bh*(Tmh-Tpcm))*(Ah-Kh))/(vh*(exp(Bh*(Tmh-Tpcm))+1)^(1/vh+1));
mode=2; //"switch heating to cooling mode"
end if;
else //"previously cooling mode"
if Tair>=Tpcm then
H= Ac+(Kc-Ac)/(1+exp(-Bc*(Tpcm-Tmc)))^(1/vc);
dHdT=-(Bc*exp(Bc*(Tmc - Tpcm))*(Ac - Kc))/(vc*(exp(Bc*(Tmc - Tpcm)) + 1)^(1/vc + 1));
mode=3; //"switch cooling to heating mode"
else
H= Ac+(Kc-Ac)/(1+exp(-Bc*(Tpcm-Tmc)))^(1/vc);
dHdT=-(Bc*exp(Bc*(Tmc - Tpcm))*(Ac - Kc))/(vc*(exp(Bc*(Tmc - Tpcm)) + 1)^(1/vc + 1));
mode=4; //"continue cooling mode"
end if;
end if;
algorithm
when {mode>0.5 and mode <1.5} then
heating_pre:=true;
end when;
when {mode>=3.5 and mode <4.5} then
heating_pre:=false;
end when;
when {mode>1.5 and mode <2.5} then
heating_pre:=false;
Kc:=(H-Ah)*((1+exp(Bh*Tmh-Bh*Tpcm))^(1/vh))+Ah;
end when;
when {mode>=2.5 and mode <3.5} then
heating_pre:=true;
Ah:=(H-Kc/((1+exp(-Bc*(Tpcm-Tmc)))^(1/vc)))/(1-1/((1+exp(-Bc*(Tpcm-Tmc)))^(1/vc)));
end when;
end LiquidFraction_modify_Q;

Related

Trying to design an 8-bit reloadable down counter

Task: Designing a 8-bit downcounter which takes an initial input value and start the downcount, and when count becomes 8'b0000_0000, it should automatically set to input value.
Ex: If given input is 8'b10010100, counter should start counting down, when value reaches 8'00000000, it should automatically reset to 8'b10010100, and again start downcount repeatedly.
For this had written a modified D flip flop using behavioral method, which works as follows:
When ld=0, output of d-flip flop q=d1 and q_bar=~d1
and when ld=1, q=d2 and q_bar=~d2
Here d2 stores the initial input values, and ld is being used as switch, i.e. when q=8'b00000000, ld=1 and sets counter output q=d2 and next cycle, ld=0 and takes d1 value.
Modified D-flip flop
module modified_d_flip_flop(q,q_bar,d1,d2,clk,ld
);
input d1,d2,clk,ld;
output q,q_bar;
reg q,q_bar;
always #(posedge clk)
begin
if(ld==0)
begin
q<=d1;
q_bar<=~d1;
end
else if(ld==1)
begin
q<=d2;
q_bar<=~d2;
end
else
begin
q<=q;
q_bar<=q_bar;
end
end
endmodule
Down Counter:
module down_counter(
input [7:0] d,
input clk,
input ld,
output [7:0] q,
output [7:0] q_bar
);
modified_d_flip_flop m_dff1 (.q(q[0]), .q_bar(q_bar[0]), .d1(q_bar[0]), .d2(d[0]), .clk(clk), .ld(ld));
modified_d_flip_flop m_dff2 (.q(q[1]), .q_bar(q_bar[1]), .d1(q_bar[1]), .d2(d[1]), .clk(q[0]), .ld(ld));
modified_d_flip_flop m_dff3 (.q(q[2]), .q_bar(q_bar[2]), .d1(q_bar[2]), .d2(d[2]), .clk(q[1]), .ld(ld));
modified_d_flip_flop m_dff4 (.q(q[3]), .q_bar(q_bar[3]), .d1(q_bar[3]), .d2(d[3]), .clk(q[2]), .ld(ld));
modified_d_flip_flop m_dff5 (.q(q[4]), .q_bar(q_bar[4]), .d1(q_bar[4]), .d2(d[4]), .clk(q[3]), .ld(ld));
modified_d_flip_flop m_dff6 (.q(q[5]), .q_bar(q_bar[5]), .d1(q_bar[5]), .d2(d[5]), .clk(q[4]), .ld(ld));
modified_d_flip_flop m_dff7 (.q(q[6]), .q_bar(q_bar[6]), .d1(q_bar[6]), .d2(d[6]), .clk(q[5]), .ld(ld));
modified_d_flip_flop m_dff8 (.q(q[7]), .q_bar(q_bar[7]), .d1(q_bar[7]), .d2(d[7]), .clk(q[6]), .ld(ld));
endmodule
Down counter Test Bench
module down_counter_tb;
reg [7:0] d;
reg clk;
reg ld;
wire [7:0] q;
wire [7:0] q_bar;
down_counter uut (
.d(d),
.clk(clk),
.ld(ld),
.q(q),
.q_bar(q_bar)
);
always #5 clk = ~clk;
initial begin
clk = 1;
ld = 1;
d = 8'b00000111;
end
initial begin
#20 ld = 0;
#20 ld = 1;
#30 ld = 0;
end
endmodule
Issue:
If initial input i.e. d2=8'b11111111, then i am getting the downcounter it works properly for the above code,
But if i give some thing like d2=8'10010011, then counter starts from 011, 010, 001 and 111, 110, 101, ........
it counts only the number of high bits from lsb + 1, if 0 is encountered next values till msb becomes x.
enter image description here
enter image description here
enter image description here
ld function too is not working as expected, when ld=0 instead of reset counter to initial input, it stops counter and starts it once ld=0.
Your code is too hard to debug because you are not designing at the proper level of abstraction. You should always use the highest level of abstraction to make the design easier to understand. Instead of designing an individual flip-flop then trying to connect them together, just design a simple counter.
With all those module instance connections, you may have a simple connection bug.
Another potential issue is a simulation race condition. Every flip-flop uses a different clock signal.
Here is a common way to design a synchronous counter. It uses the same clock for all flops of the counter:
module down_counter (
input [7:0] d,
input clk,
input ld,
output reg [7:0] q
);
always #(posedge clk) begin
if (ld || (q == 0)) begin
q <= d;
end else begin
q <= q - 1;
end
end
endmodule
module down_counter_tb;
reg [7:0] d;
reg clk;
reg ld;
wire [7:0] q;
down_counter uut (
.d(d),
.clk(clk),
.ld(ld),
.q(q)
);
always #5 clk = ~clk;
initial begin
clk = 1;
ld = 1;
d = 7;
repeat (2) #(posedge clk);
ld <= 0;
repeat (15) #(posedge clk);
ld <= 0;
d <= 8'b1001_0011;
repeat (1) #(posedge clk);
ld <= 0;
repeat (500) #(posedge clk);
$finish;
end
endmodule
By using nonblocking assignments (<=) and driving the inputs on #(posedge clk) in the testbench (as is done in the design), we also avoid race conditions in the testbench.
You didn't provide a thorough description of the ld signal. The code I showed loads the counter with the 8-bit input data (d) when ld=1. When ld=0, the counter counts down. When it reaches 0, the counter is automatically reloaded with d.
Thanks #toolic
You code surely gave me an idea. Modified it a little to solve my issue
I am trying to design a frequency divider for my project for that i needed this downcounter.
ld - Use was to make the counter reset to my expected value when ld=0 and again make ld=1 next cycle to start the downcount and again when downcounter value became 0, make ld=0 to reset the counter to expected value. This had to go on forever.
In your testbench we have to set it many times.
I just wanted to give one initial value and i wanted it to run forever.
I modified your code, to get my desired result.
I removed ld and added, initial q = 0
Down Counter
module down_counter(
input [7:0] d,
input clk,
output reg [7:0] q
);
initial q = 0;
always #(posedge clk)
begin
if (q == 0)
begin
q <= d;
end
else
begin
q <= q-1;
end
end
endmodule
Testbench:
module down_counter_tb;
// Inputs
reg [7:0] d;
reg clk;
// Outputs
wire [7:0] q;
// Instantiate the Unit Under Test (UUT)
down_counter uut (
.d(d),
.clk(clk),
.q(q)
);
always #5 clk=~clk;
initial begin
// Initialize Inputs
d = 8'b00000100;
clk = 1;
end
endmodule
Waveform:

What does the PINNAME to PINNAME data path in Xilinx ISE synthesis timing report mean?

I've written a simple DFF with the following VHDL code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity DFF is
port (d: in STD_LOGIC;
q: out STD_LOGIC;
clk: in STD_LOGIC;
reset: in STD_LOGIC);
end DFF;
architecture Behavioral of DFF is
begin
process (reset, clk) begin
if (reset = '1') then
q <= '0';
elsif (rising_edge(clk)) then
q <= d;
end if;
end process;
end Behavioral;
I subsequently run simulation and synthesis. When I examine the synthesis report, in the Timing Report section, this is present:
=========================================================================
Timing constraint: Default OFFSET OUT AFTER for Clock 'clk'
Total number of paths / destination ports: 1 / 1
-------------------------------------------------------------------------
Offset: 3.597ns (Levels of Logic = 1)
Source: q (FF)
Destination: q (PAD)
Source Clock: clk rising
Data Path: q to q
Gate Net
Cell:in->out fanout Delay Delay Logical Name (Net Name)
---------------------------------------- ------------
FDC:C->Q 1 0.447 0.579 q (q_OBUF)
OBUF:I->O 2.571 q_OBUF (q)
----------------------------------------
Total 3.597ns (3.018ns logic, 0.579ns route)
(83.9% logic, 16.1% route)
=========================================================================
What does the q to q data path signify, and what does it even mean?

Lua Love2d Quadtree recursion

UPDATE -- I figured it out. Turns out I am bad at math and visualizing 2d points. I wasn't setting south or east subdivisions correctly.
I have been trying to make a quadtree to track points in Love2d. I have the most of the code written, but I don't think the recursion is working properly.
I'm pretty new to the coding scene, so I really don't know where to start.
It seems to leave out points that go into the southeast quadrant.
I think as it goes recursively into the insert function it either looks at the parents point array or doesn't seem to go into all the insert functions.
local QuadTree = {}
QuadTree.__index = QuadTree
function QuadTree:new(boundary,capacity)
local quadTemp = {}
setmetatable(quadTemp, QuadTree)
if (not boundary) then
print('No boundary given to new QuadTree')
end
if (type(capacity) ~= 'number') then
print('Boundary should be a number')
end
if (capacity < 1) then
print('capacity should be greater than one')
end
quadTemp.boundary = boundary
quadTemp.capacity = capacity
quadTemp.points = {}
quadTemp.hasDivided = false
return quadTemp
end
function QuadTree:insert(p)
--If this point doesnt belong in this spot dont add it
if (not self.boundary:contains(p)) then
return false
elseif (#self.points<self.capacity) then
table.insert(self.points,p)
return true
elseif(not self.hasDivided) then
self:subdivide()
elseif(self.hasDivided) then
return self.northeast:insert(p) or
self.northwest:insert(p) or
self.southeast:insert(p) or
self.southwest:insert(p)
end
end
function QuadTree:subdivide()
local x = self.boundary.xpos
local y = self.boundary.ypos
local w = self.boundary.width / 2
local h = self.boundary.height / 2
local nw = Rectangle:new(x,y,w,h)
self.northwest = QuadTree:new(nw,self.capacity)
local ne = Rectangle:new(w,y,w,h)
self.northeast = QuadTree:new(ne,self.capacity)
local sw = Rectangle:new(x,h,w,h)
self.southwest = QuadTree:new(sw,self.capacity)
local se = Rectangle:new(w,h,w,h)
self.southeast = QuadTree:new(se,self.capacity)
self.hasDivided = true
end
function QuadTree:query(range,found)
--If we havent found any yet lets create a list incase we do
if (not found) then found = {} end
--If this cell doesnt contain the boundary then return an empty list
if (not range:intersects(self.boundary)) then
return found
end
for k,v in pairs(self.points) do
if (range:contains(v)) then
table.insert(found,v)
end
end
--If the current cell has divided we need to check its children
if (self.hasDivided) then
self.northwest:query(range,found)
self.northeast:query(range,found)
self.southwest:query(range,found)
self.southeast:query(range,found)
end
return found;
end

VHDL directly comparing vectors

I was wondering if its possible to directly compare 2 vectors with eachother instead of just looking at them bit by bit.
For example:
entity Comparator is
port(a,b in: std_logic_vector (2 downto 0);
out1, out2 out: std_logic);
end Comparator;
architecture behavioural of Comparator1 is
begin
if a = b then
out1 <= '1'
else if /= then
out2 <= '1'
end if;
end behaviour;
Is this possible?
The answer is yes, you can compare two array types of the same type and subtype indication directly.
However your example code isn't valid.
The result of the expression a=b is boolean. You convert that to std_logic by assigning out1 and out2. An if statement in this context has to be in a process statement. Also you don't need two outputs:
architecture foo of Comparator1 is
begin
UNLABELED:
process (a,b)
begin
if a = b then
out1 <= '1';
else
out1 <= '0';
end if;
end process;
end architecture;
Alternative a concurrent signal assignment statement, a conditional signal assignment that has an equivalent process to that above:
architecture fum of Comparator1 is
begin
UNLABELED:
out1 <= '1' when a = b else '0';
end architecture;
You can also use to_integer(unsigned(a)) and threat them as integers.
For example:
IF(to_integer(unsigned(a)) < to_integer(unsigned(b))) THEN

Assistance with Lua Cosine, wrong results returned

Ok, first up, this is NOT for a class, test, or other student type activity.
I'm a scripter for a game, and am trying to implement the math library for all to use, and unfortunately, all I have available to me is very basic lua. The implemented version cannot be changed, and does not include any libraries. For those wondering, its for scripting in Fold.It.
Here's what I have...
math={}
math.fact = function(b) if(b==1)or(b==0) then return 1 end e=1 for c=b,1,-1 do e=e*c end return e end
math.pow = function(b,p) e=b if(p==0) then return 1 end if(p<0) then p=p*(-1) end for c=p,2,-1 do e=e*b end return e end
math.cos = function(b,p) e=0 p=p or 10 for i=1,p do e=e+(math.pow(-1,i)*math.pow(b,2*i)/math.fact(2*i)) end return e end
To clarify above, math.fact returns factorial, which is returning accurate to about 10 points of precision, and is a new function I've done to aid in cosine calculation.
The math.pow is also a new function to handle returning powers, also working as expected.
The issue is with the cosine function. Its returning unexpected values. Here's an easier to digest version (I've been writing my library stuff ultra lean)...
function math.cos(value,precision)
result=0
precision=precision or 10
for i=1,precision do
result=result+(math.pow(-1,i)*math.pow(value,2*i)/math.fact(2*i))
end
return e
end
The problem is, with those functions, for print(math.cos(90)) it returns 4.77135... when I'm expecting -0.44807... (based on calc in scientific mode, or using an online tool to cos(90)).
I'm also having issues with sin and tan, however they are similarly written to cos, which seems to have been done in many languages. If I can figure out what I'm doing wrong, I can get them all fixed.
EDIT: Corrected typo
First, your lua doesn't run. Second, you need to make your variables local. Third, cosine starts with a one.
The problem is because the Taylor series you are using only converges on the correct values of cosine close to zero. You would have to use a far more terms of the series to get it to handle 90 correctly. You can fix this for your implementation two ways:
Add a pi constant. Then use a while loop to adjust the value such that abs(value) < 2*pi:
math.pi = 3.14159265358
while value > math.pi*2 do
value = value - math.pi * 2
end
while value < -math.pi*2 do
value = value + math.pi * 2
end
Or - find or implement a version of fmod in lua.
Here is the corrected code (you can minify it):
math={}
math.fact = function(b)
if(b==1)or(b==0) then
return 1
end
local e=1
for c=b,1,-1 do
e=e*c
end
return e
end
math.pow = function(b,p)
local e=b
if(p==0) then
return 1
end
if(p<0) then
p=p*(-1)
end
for c=p,2,-1 do
e=e*b
end
return e
end
math.cos = function(b,p)
local e=1
b = math.correctRadians(b)
p=p or 10
for i=1,p do
e=e+(math.pow(-1,i)*math.pow(b,2*i)/math.fact(2*i))
end
return e
end
math.pi = 3.1415926545358
math.correctRadians = function( value )
while value > math.pi*2 do
value = value - math.pi * 2
end
while value < -math.pi*2 do
value = value + math.pi * 2
end
return value
end
interactive lua run:
imac:~ root$ lua -i temp.lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> print( math.cos( 90 ) )
-0.44807359244883
>

Resources