How to make ACLK centric data transfer - fpga

In the AXIS stream speck the ACLK is defined as:
The global clock signal. All signals are sampled on the rising edge of
ACLK.
Which means that it is assumed that AXIS master and slave are receiving the same ACLK.
Can you please help understand following:
1) If there is a ACLK slew on AXIS master and slave blocks,it is left under designer responsibility. Speck does not set any limitation on that. Is my understanding right?
2) The data transfer should be ACLK center aligned. So the developer should make the AXIS master to send clock center aligned data. Right?
3) How to make ACLK centric data transfer? Imagine you have global clock in the whole system, to make data to be transferred clock center aligned to that data, you need to generate new clock which has phase left shifted from your global clock. Any ideas how we can do it in FPGA?

I think the problem is in your understanding of English.
-centric is not the same as centre (or center).
Centric means here "The most important, where everything revolves around"
It does not mean that the data is in the middle (centre) of the clock.
Thus in an AXI/AMBA system you must make sure all components use the same clock signal and all logic should run from the rising clock edge. That is in the same, standard, requirement of all synchronous logic.
Now to answer your questions:
1) If there is a ACLK slew on AXIS master and slave blocks,it is left under designer responsibility. Speck does not set any limitation on that. Is my understanding right?
You should not have clock skew. If you have, your are in deep trouble and yes, you have to solve that. Avoid it at all cost!
2) The data transfer should be ACLK center aligned. So the developer should make the AXIS master to send clock center aligned data. Right?
No. Everything is clocked of the rising clock edge. Which means the data will start changing shortly after that rising clock edge. You can see this in all the timing diagrams which are in the AXI/AMBA standard.
3) How to make ACLK centric data transfer? Imagine you have global clock in the whole system, to make data to be transferred clock center aligned to that data, you need to generate new clock which has phase left shifted from your global clock. Any ideas how we can do it in FPGA?
All you do is use the same ACLK signal everywhere. Do not shift the clock, do not generate a new clock.
Here are some Verilog modules I designed:
module ahbl_arbiter
#(parameter MA = 4 // Number of masters 2..8
)
( input clk, // System clock
input reset_n, // System reset
input clken, // Clock enable
....
module ahbl_splitter
#(parameter SL = 4, // Number of slaves 2..32
L2BS = 10 // Log 2 of block size 10 = 1K
)
( input clk, // System clock
input reset_n, // System reset
input clken, // Clock enable
....
module apb_bridge
#(parameter
NS = 8, // Number of slaves
L2BS = 10, // Log2 Address block assigned each peripheral
REG = 1'b0 // Register in rdata return path
)
( input clk, // System clock
input reset_n, // System reset
input clken, // Clock enable
...
If you use these they all have the same clock:
ahbl_arbiter
ahbl_arbiter_0 (
.clk (aclk), // System clock
.reset_n (reset_n), // System reset
.clken (clken), // Clock enable
....
apb_bride
apb_bride_0 (
.clk (aclk), // System clock
.reset_n (reset_n), // System reset
.clken (clken), // Clock enable
....
ahbl_splitter
ahbl_splitter_0 (
.clk (aclk), // System clock
.reset_n (reset_n), // System reset
.clken (clken), // Clock enable
....

Related

GPIO32 pin works in analog mode, always reads 0 in digital mode

I'm having some difficulty getting PCNT pulse counting working with a prototype ESP32 device board.
I have a water level sensor (model D2LS-A) that signals state by the frequency of a square wave signal it sends to GPIO32 (20Hz, 50Hz, 100Hz, 200Hz, 400Hz).
Sadly, the PCNT counter stays at 0.
To troubleshoot, I tried putting GPIO32 in ADC mode (attenuation 0, 10-bit mode) to read the raw signal (sampling it many times a second), and I'm getting values that I would expect (0-1023). But trying the same thing using digital GPIO mode, it always returns 0, never 1 in all the samples.
Since the PCNT ESP IDF component depends on reading the pin digitally, the counter never increments past 0.
So the real problem I'm having is: why aren't the ADC readings (between 0-1023) translating to digital readings of 0-1 as one would expect?

Given the data path of the LC-3 (provided below), give a complete description of the STORE DIRECT instruction (ST SR, label), as follows

I've tried reading the book but I'm not sure exactly how to go about this. Anyone have an idea?
So in doing these problems its best to have the datapath in front of you and have the Register Transfer Language written down, you do these problems step by step, it is a little daunting, but following all of the Digital Logic you have learned it is all a matter of you being a pirate and the datapath being your treasure map.
To do this you just follow the wires in the diagram. I'm using this one which I'm sure is in the Patt/Patel textbook https://i.ytimg.com/vi/PeWbyffnkZ4/maxresdefault.jpg
Mem[PC + SEXT(IR[8:0])] = SR
Clock Cycle 1
So the first thing you need to do is SEXT(IR[8:0]) So where in the datapath is a sign extender and where is the IR. If you look at the ADDR2MUX you see it has 4 inputs each being bits from the IR and one with 0. So ADDR2MUX=IR[8:0]
Next we need to add the PC to it. So from the output of the ADDR2MUX will be the SEXT(IR[8:0]) So next we need to add the PC to that output. Well we see the output of the ADDR2MUX feeds into an adder. So ok we need to set the other adder up with the PC. The ADDR1MUX has an input from the register file and the PC. So ADDR1MUX=PC
Both of these inputs go into the adder and now the output of that adder has PC + SEXT(IR[8:0])
Next we need to store to memory, the address we want to store to is PC + SEXT(IR[8:0]), and what we want to store is SR. So how do we do that? To interface with memory we need to put the address in the MAR (Memory Address Register) and the data we want to store in the MDR. So lets do the MAR step first. So we need to put the result of the ADDER into the MAR. The only path we can take is the MARMUX. So MARMUX=ADDER. We need to Gate the MARMUX to put it out on the bus as well. So GateMARMUX.
The value of the MARMUX is now out onto the bus so we want to latch that into the MAR so LDMAR.
We need a new clock cycle now because we need to wait for the value to latch into the register which happens at the beginning of a new clock cycle.
Clock Cycle 1 Signals - ADDR2MUX=IR[8:0], ADDR1MUX=PC, MARMUX=ADDER, GateMARMUX, LDMAR
Clock Cycle 2
Now lets the source register into the MDR. Looking at the diagram we need a path from the register file to the BUS to get it into the MDR. There's actually two ways of doing this one going through ADDR1MUX and one going through the ALU.
I will take the ALU path as its slightly more correct.
First we need to make SR1 be the source register from the instruction so SR1MUX=[11:9]
The Source register from the instruction now comes out the register file from the SR1 output, this feeds into the ALU. So we must choose the operation the ALU does so, ALUK=PASSA. PASSA simply makes the output of the ALU the 'A' input.
We then need to put the ALU output on the bus so GateALU
Now the ALU output is on the bus and we want to store this in the MDR, however there is a MUX blocking that input. MIO.EN=0 to select the bus output to go into the MDR. Then we need to latch that value into the register so LDMDR
We just tried to load a value into a register so it will not be available in the output until the start of the next clock cycle so..
Clock Cycle 2 Signals - SR1MUX=[11:9], ALUK=PASSA, GateALU, MIO.EN=0, LDMDR
Clock Cycle 3
All we need to do is give memory a good ol kick to store the value in the MDR at the address in the MAR so... MIO.EN=1, R/W=W
Clock Cycle 3 signals - MIO.EN=1, R/W=W
So this concludes the ST instruction it takes 3 clock cycles and the signals to assert each clock cycle are indicated at the end of each clock cycle. All of those signals per clock cycle can be turned on at the same time.

Multiple PWM Channels on PIC

I use the PIC16F88 for my project, with XC8 compiler.
What I'm trying to achieve is to control 4 LEDs with 4 buttons, when you press a buttons it increases the duty cycle of the corresponding LED by 10%.
When you press the button on RB0 it increases the duty cycle of the LED on RB4, and so on.
Every LED is independent, therefore it can have a different duty cycle.
The problem is that the PIC i'm using only have one PWM module on either RB0 or RB3 (using CCPMX bit).
After some research I decided to implement software PWM to have four different channels, each channels would control one duty cycle, but most of the sources I found didn't provide any explanation on how to do it.
Or is there a way to mirror PWM to multiple pins ?
Thanks by advance for helping me out.
Mirroring is not an option.
PWM is relatively simple. You have to set PWM frequency (which you will not change) and PWM duty cycle (which you need to change in order to have 0-100% voltage range). You have to decide about resolution of PWM, voltage step that you need (built in PWM for example is 8-bit and has 0-255 steps).
Finally, you have to set timer to interrupt based on PWM frequency * PWM resolution. In Timer ISR routine you need to check resolution counts and PWM value of all your channels. Resolution count will have to reset when resolution value is reached (and start to count from 0 again, all outputs go HIGH here, also). When PWM value of output is reached you have to toggle (pull it LOW) corresponding pin (and reset it back to HIGH with every resolution count reset).
This is only one way of doing it, involves only one timer and should be most simple since your PIC is low with resources.
Hope it helps...

SET A VALUE TO PIN BY MONITORING SAME PIN IN VHDL

Is it possible to set an inout pin to specific value when after monitoring the value in same pin.ie if we have an inout signal then if value on that signal is one then after doing specific operation can we set value of that pin to zero in vhdl.
What you are describing doesn't make a lot of sense. Are you sure you are understanding the requirements correctly?
Your load signal sounds like an external control signal that is an input into your module. You should not be trying to change the value of that signal - whoever is controlling your module should do that instead.
As long as the load signal is asserted (1), you should probably be loading your shift register with whatever value is presumably being provided on a different input signal (e.g., parallel_data). When the load signal is deasserted (0) by the external logic, you should probably start shifting out one bit of the loaded data per clock cycle to your output signal (e.g., serial_data).
Note that there is no need for bidirectional signals!
This is all based on what I would consider typical behavior for a shift register, and may or may not match what you are trying to achieve.
This doesn't sound like a good plan, and I'm not entirely sure you want to do it, but I guess if you can set things up such that:
you have a resistor pulling the wire down to ground.
your outside device drives the wire high
the FPGA captures the pin going high and then also drives it high
The outside source goes tristate once it has seen the pin go high
the FPGA can then set the pin tristate when it wants to flag it has finished (or whatever), and the resistor will pull it low again
repeat
I imagine one use for this would be for the outside device to trigger some processing and the FPGA to indicate when it has finished, in which case, the FPGA code could be something like:
pin_name <= '1' when fpga_is_processing = '1' else 'Z';
start_processing <= '1' when pin_name = '1' and pin_name_last = '0';
pin_name_last <= pin_name when rising_edge(clk);
start processing will produce a single clock pulse on the rising edge of the pin_name signal. fpga_is_processing would be an output from your processing block, which must "come back" before he external device has stopped driving the pin high.
You may want to "denoise" the edge-detector on the pin_name signal to reduce the chances of external glitches triggering your processing. There are various ways to achieve that also.

VHDL code for pulse signal with variable working cycle

I need to create a VHDL code for this situation:
**Draw a control circuit that generates a pulse signal with:
fixed working frequency (100 KHz)
variable working cycle
The phase difference should be increased or decreased by the direction of the spin of a rotary control of 8 bits.**
Additional info:
D = t (on) / T
D = working cycle
t (on) = Time the activated signal lasts (rotary control of 8 bits)
T = signal period (constant)
You seem to be wanting to generate a mark:space ratio of between 1:255 and 255:1, so you will need a clock frequency of 256 * 100kHz.
An 8 bit incrementing counter can be left free-running clocked at that rate.
Now have a flop that is SET when the counter overflows from X'FF to X'00 and that CLEARS when the timer value makes the transition from N-1 to N. Where N is the 8 bit value on your duty cycle setting control and controls the width of the mark.
The threshold controlled flop's output is your variable duty cycle 100kHz.

Resources