Doubling system clock freq doesn't halve simulated time? - gem5

I am playing in the SE mode, with script 'GEM5_PATH/configs/learning_gem5/part2/simple_memobj.py', where I altered frequencies between:
# Set the clock fequency of the system (and all of its children)
system.clk_domain = SrcClockDomain()
system.clk_domain.clock = **'1GHz'**
and
# Set the clock fequency of the system (and all of its children)
system.clk_domain = SrcClockDomain()
system.clk_domain.clock = **'2GHz'**
I read the first line from "stats.txt" about the sim_seconds, 1GHz takes 0.000508s, while 2GHz takes 0.000459s, which is not halved as overall system frequency is doubled. Any hints about the reason? Any other configs needed to make it as desired?
The command is:
build/X86/gem5.opt configs/learning_gem5/part2/simple_memobj.py
The benchmark is:
'tests/test-progs/hello/bin/x86/linux/hello'
Thanks a lot.

Related

How does a reference clock "drive" a VCO

Reading the following chapter:
https://users.ece.utexas.edu/~valvano/Volume1/E-Book/C10_FiniteStateMachines.htm
In the beginning, on top of Figure 10.1, the author claims that:
Because the reference clock is stable, the feedback loop in the PLL will drive the output to a stable 400 MHz frequency.
Question: How does a 16MHz clock drive a 400MHz PLL? (I checked the wiki for PLL but didn't understand much)
A bit of background: I don't know much about electronics, and apparently this book doesn't really require students to understand such questions (it focuses on writing C programs for an eval board). I'm just curious.
In simple words: A PLL works by "comparing" the reference frequency with its own frequency. If its frequency is too low, it raises it a bit, and if it's too high, it lowers it a bit. This is what the feedback loop does. (Actually, the phase is used for comparison. That's why it's called a "phase lock[ed] loop".)
So your question boils down to: How can a frequency of 400 MHz be compared with a frequency of 16 MHz?
Well, as such, it cannot. For the comparison in the "Phase/Freq Detector" both frequencies need to be nearly the same. "Nearly" because while not being locked, the VCO's frequency might be "off track".
The solution is to divide the 400 MHz down to 16 MHz, by the value of 25. This is what the block "/m" in the linked page does:
The "programming" aspect in your question: You set up the divisor by choosing the right XTAL from the table.
After division, the detector receives two frequencies in the same range.

timing issues: simulation (iverilog, gtkwave) works, hardware (yosys) does not

I am learning verilog, trying do make the "hello world" in the VGA world (a bouncing ball) on a ice40LX1K board (olimex ice40HX1K + VGA I/O board).
I have a strange problem: when I simulate my design using iverilog + GTKWave, it seams to work good. But the implementation in hardware does not work.
What is strange is that in the hardware implemention, the ball is doesn't move .. and its position is all zero (0,0) althou the verilog code never should set it overthere.
It looks like changing the value of xpos_ball or ypos_ball does not actually change these values. (a hardware issue? a yosys issue)? In the iverilog simulation, location of the ball does change as expected.
I have no idea if this is a error in my own verilog code (as I am new in this, this is very well possible), an issue in yosys, or a problem in the hardware (speed issue, is the 100 Mhz clock to fast?) or something else?
Any proposals on how to troubleshoot this, or next steps for this kind of issue? Are there other debugging-tricks I can use?
(edit: link to the actual verilog-code removed as not relevant anymore)
Kristoff
is the 100 Mhz clock to fast?
Yes. That design is good for 39.67 MHz:
$ make vga_bounceball.rpt
icetime -d hx1k -mtr vga_bounceball.rpt vga_bounceball.asc
// Reading input .asc file..
// Reading 1k chipdb file..
// Creating timing netlist..
// Timing estimate: 25.21 ns (39.67 MHz)
Edit re comment:
You can always safely divide a clock by a power of two by using FFs as clock dividers:
input clk_100MHz;
reg clk_50MHz = 0; // initialization needed for simulation
reg clk_25MHz = 0;
always #(posedge clk_100MHz) clk_50MHz <= !clk_50MHz;
always #(posedge clk_50MHz) clk_25MHz <= !clk_25MHz;
(A non-power-of-two prescaler is not always safe without making sure with timing analysis that the prescaler itself can run in the high frequency domain.)

Reading incorrect temperature value from thermistor using EVK1100

I want to get the temperature from a thermistor, so I made a voltage divider (3.3V to 10k resistor and between ground a 10k thermistor) I read the ADC between the 10k resistor and the thermistor.
The BCOEFFICIENT is 3977, the NOMINAL TEMPERATURE is 25C and I use the simple B parameter equation. I'm not sure where I'm doing mistake, I read room temperature as 10.5C which was suppose to be around 24C. The following is the part of the program that I used for temperature sensor(developed in AVR studio),
#define TEMPERATURENOMINAL 25
#define TERMISTORNOMINAL 10000
#define BCOEFFICIENT 3977
#define SERIESRESISTOR 10000
{
float ke1,tempa,xin
ke1 = adc_get_value(peak_adc2,peak2);
xin=(1023/ke1)-1;
xin=SERIESRESISTOR/xin;
tempa=xin/TERMISTORNOMINAL;
tempa=log(tempa);
tempa/= BCOEFFICIENT;
tempa+=1.0/(TEMPERATURENOMINAL + 273.15);
tempa=1.0/tempa;
tempa-=273.15;
dip204_set_cursor_position(1,3);
//sprintf(ui, "Temp is %.2f deg", Ref);
sprintf(ui, "Temp is %.2f deg", tempa);
dip204_write_string(ui);
}
I checked the voltage using multi-meter for instance in between the thermistor and 10k resistor and in the EVK 1100 using the following line
ke1 = adc_get_value(peak_adc2,peak2)*3.3/1024;
I get the same voltage in both.
Not sure where I'm doing a mistake, Hope someone guide me in right direction
Your code looks correct to me, and I suspect a hardware problem may be the culprit.
It seems likely you have inadvertently connected two 10K-ohm pull-up resistors between the ADC input and the +3.3V reference: perhaps one is already populated on the EVK1100 board, and you have added another one externally connected to your thermistor. This would be equivalent to putting both 10K-ohm resistors in parallel with each other, which would be equivalent to a 5K-ohm resistor in series with the thermistor. At 25°C, the thermistor resistance Rt would read 10K ohms, which would produce a voltage of:
+3.3V * (Rt / (Rt + 5K))
= 2.20V
instead of the correct +1.65V. This number is very close to the result you are seeing (+2.17V # 24°C).
You can verify this hypothesis by looking at the schematic and/or PCB for the EVK1100 to see if a 10K-ohm pull-up resistor is connected from the ADC input to +3.3V. If this is the problem, remove one of the two resistors and you should see correct behavior.

measuring time between two rising edges in beaglebone

I am reading sensor output as square wave(0-5 volt) via oscilloscope. Now I want to measure frequency of one period with Beaglebone. So I should measure the time between two rising edges. However, I don't have any experience with working Beaglebone. Can you give some advices or sample codes about measuring time between rising edges?
How deterministic do you need this to be? If you can tolerate some inaccuracy, you can probably do it on the main Linux OS; if you want to be fancy pants, this seems like a potential use case for the BBB's PRU's (which I unfortunately haven't used so take this with substantial amounts of salt). I would expect you'd be able to write PRU code that just sits with an infinite outerloop and then inside that loop, start looping until it sees the pin shows 0, then starts looping until the pin shows 1 (this is the first rising edge), then starts counting until either the pin shows 0 again (this would then be the falling edge) or another loop to the next rising edge... either way, you could take the counter value and you should be able to directly convert that into time (the PRU is states as having fixed frequency for each instruction, and is a 200Mhz (50ns/instruction). Assuming your loop is something like
#starting with pin low
inner loop 1:
registerX = loadPin
increment counter
jump if zero registerX to inner loop 1
# pin is now high
inner loop 2:
registerX = loadPin
increment counter
jump if one registerX to inner loop 2
# pin is now low again
That should take 3 instructions per counter increment, so you can get the time as 3 * counter * 50 ns.
As suggested by Foon in his answer, the PRUs are a good fit for this task (although depending on your requirements it may be fine to use the ARM processor and standard GPIO). Please note that (as far as I know) both the regular GPIOs and the PRU inputs are based on 3.3V logic, and connecting a 5V signal might fry your board! You will need an additional component or circuit to convert from 5V to 3.3V.
I've written a basic example that measures timing between rising edges on the header pin P8.15 for my own purpose of measuring an engine's rpm. If you decide to use it, you should check the timing results against a known reference. It's about right but I haven't checked it carefully at all. It is implemented using PRU assembly and uses the pypruss python module to simplify interfacing.

How to make Timer1 more accurate as a real time clock?

I have PIC18F87J11 with 8 MHz oscillator and I am using timer1 as real time clock. At this moment I have it toggle an LED every 1 minute. I noticed it does work perfect fine the first few times but slowly it starts toggling the LED every 59 seconds. Then every few minutes it keeps going down to 58, 57, etc. I don't know if its impossible to get an accurate clock using internal oscillator or if I need external oscillator. My settings look right for timer1, I just hope I can resolve this issue with the current hardware.
Prescaler 1:8, TMR1 Preload = 15536, Actual Interrupt Time : 200 ms
// Timer 1 Settings
RCONbits.IPEN = 1; // Enable interrupt system priority feature
INTCONbits.GIEL = 1; // Enable low priority interrupts
// 1:8 prescalar
T1CONbits.T1CKPS1 = 1;
T1CONbits.T1CKPS0 = 1;
// Use Internal Clock
T1CONbits.TMR1CS = 0;
// Timer1 overflow interrupt
PIE1bits.TMR1IE = 1;
IPR1bits.TMR1IP = 0; // Timer 1 -> Low priority interrupt group
PIE1bits.TMR1IE = 1; // Enable Timer1 interrupt
// TMR1 Preload = 15536;
TMR1H = 0x3C;
TMR1L = 0xB0;
Interrupt Routine
void interrupt low_priority lowISR(void) {
if (PIR1bits.TMR1IF == 1) {
oneSecond++;
if (oneSecond == 5) {
minute_Counter++;
if (minute_Counter >= 60) {
// One minute passed
Printf("\r\n One minute Passed");
ToggleLed();
minute_Counter = 0;
}
oneSecond = 0;
}
// TMR1 Preload = 15536;
TMR1H = 0x3C;
TMR1L = 0xB0;
PIR1bits.TMR1IF = 0;
}}
The internal oscillator is a simple RC oscilator (a resistor/capacitor time constant determines its frequency), this kind of circuit may be accurate to only +/-10% over the operating temperature range of the device, and the device will be self-heating due to normal operating power dissipation.
From the data sheet:
An external crystal or other accurate external clock source is required to get accurate timing. Alternatively, if you have some other stable and accurate, but low frequency clock source, such as output from an RTC with a 38768 Hz crystal, you can use that to calibrate the internal RC oscillator and dynamically adjust it with the OSCTUNE register - by using a timer gated by the low frequency source, you can determine the actual frequency of INTOSC and adjust accordingly - it will not be perfect, but it will be better - but no better than the precision of the calibrating source of course.
Some devices have a die temperature sensor that can also be used to compensate, but that is not available on your device.
The RC error can cause serial communications mistiming to the extent that you cannot communicate with a device using asynchronous (UART) serial comms.
There are some stuff in the datasheet you linked, "2.5.3 INTERNAL OSCILLATOR OUTPUT FREQUENCY AND TUNING", on p38
The datasheet says that
The INTOSC frequency may drift as VDD or temperature changes".
Are VDD and temperature stable ?
It notes three ways to deal with this by tuning the OSCTUNE register. The three of them would need an external "oscillator" :
dealing with errors of EUSART...this signal should come from somewhere.
a peripheral clock
cpp module in capture mode. You may use any stable AC signal as input.
Good luck !
Reload the Timer as soon as it expires, the delay between timer overflow and rearm is affecting the total time. So this will solve your problem.
void interrupt low_priority lowISR(void)
{
if (PIR1bits.TMR1IF)
{
PIR1bits.TMR1IF = 0;
TMR1H = 0x3C;
TMR1L = 0xAF;
/* rest of the code here */
. . . .
}
}
One more recommendation is not to load up the isr, keep it simple.
For all timing, time and frequency applications the first and most important thing to do is to CALIBRATE THE CRYSTAL OSCILLATOR!!! The oscillator itself and its crystal MUST run exactly (to better than 1 part per million = 1ppm) of its nominal frequency. Crystals straight out of a factory (except some very specialized and expensive ones = 100's of $) are not running exactly at their nominal frequency. If the calibration is not done, all time and frequency related functions will be off, because the oscillator frequency is used as reference for all PICs internal functions. The calibration must be done against an accurate frequency counter by adjusting one of the capacitors from crystal pins to ground. Any processor routines for frequency (and time) calibration are not accurate enough.