M
M. Norton
This one has me stumped on how to implement the proper behavior, so
I'm going to check with the conventional wisdom of USENET ;-).
Here is the situation. We have an FPGA talking to a DAC on another
board via I2C. For purposes most likely involving voltage level and
protection, the data line is buffered in the following fashion.
The DAC only has one data line, SDA.
The FPGA has two data lines, SDO, SDI.
SDI is always a buffered version of SDA. That part is generally easy.
SDO is wired to the negative enable of a tri-stateable buffer. The
input to the buffer is ground. There is a moderately low strength
pull-up on the output (1kohm). I have zero idea of the capacitance on
this line. They've done this trick before with no issues and the data
rate is fairly low and they seem to be happy with the results. I'm
just verifying the communications behavior with the DAC as best I
can.
Anyhow, so when the FPGA is controlling the bus, it modulates SDO.
When SDO = 0, the SDA bus is strongly pulled to ground. When SDO = 1,
the bus is weakly pulled to 1. When the driver on the DAC side is
active, it can pull the bus around, and otherwise tristated.
To start, I'm not going to try to model rise-fall times. I can add
that in later if it needs it (and honestly I don't know that anyone
ever measured the capacitance of the bidirectional line)
So far I have (with declarations sketched in)
entity tb
port (...
sdo : in std_logic;
sdi : out std_logic;
... );
end tb;
architecture foobar of tb is
signal sda : std_logic;
component dac_model
port (...
sda : inout std_logic;
... );
end component;
begin
DAC_BUFFER_MODEL : process (sdo, sda)
begin
if (sdo = '0') then
sda <= '0';
else
sda <= 'H';
end if;
--
-- The pin back to the FPGA should always be whatever is on sda
--
sdi <= sda;
end process;
my_dac : dac_model
port map (
sda => sda,
...);
So... is this going to do what I want it to do? Looks like I assign
sda a weak high if sdo is not low. I can make sure that the dac_model
treats sda properly (either 1, 0, or Z). I just hope that H will
resolve to 1 when it matters. I've spent most of my time in RTL and
have never, ever used the other values of std_logic since they don't
exist inside an FPGA.
Since there's no proper tristate command, I'm not able to guess when
the FPGA wants to tristate the bus and when it just wants to signal a
'1'. However I know the interior of the FPGA is also not written to
worry about 'H's versus '1's so at some point it has to be resolved
into very discrete levels.
Writing this, I just had the thought that I need to do this in my
process. So instead of the sdi <= sda assignment, perhaps something
here that resolves everything into real values would be good. However
I'm not sure how to go about this other than a brute force case
statement like:
case sda is
when '1' => sdi <= '1';
when '0' => sdi <= '0';
when 'H' => sdi <= '1';
when ...
Etc. You get the picture. Surely there's a better way to do this.
Any ideas out there? Anyone seen this setup before? I'd draw a
picture, but Google Groups doesn't do fixed space text input so I only
have the faintest idea of how it'd look. Hopefully I described it
well enough.
Best regards,
Mark Norton
I'm going to check with the conventional wisdom of USENET ;-).
Here is the situation. We have an FPGA talking to a DAC on another
board via I2C. For purposes most likely involving voltage level and
protection, the data line is buffered in the following fashion.
The DAC only has one data line, SDA.
The FPGA has two data lines, SDO, SDI.
SDI is always a buffered version of SDA. That part is generally easy.
SDO is wired to the negative enable of a tri-stateable buffer. The
input to the buffer is ground. There is a moderately low strength
pull-up on the output (1kohm). I have zero idea of the capacitance on
this line. They've done this trick before with no issues and the data
rate is fairly low and they seem to be happy with the results. I'm
just verifying the communications behavior with the DAC as best I
can.
Anyhow, so when the FPGA is controlling the bus, it modulates SDO.
When SDO = 0, the SDA bus is strongly pulled to ground. When SDO = 1,
the bus is weakly pulled to 1. When the driver on the DAC side is
active, it can pull the bus around, and otherwise tristated.
To start, I'm not going to try to model rise-fall times. I can add
that in later if it needs it (and honestly I don't know that anyone
ever measured the capacitance of the bidirectional line)
So far I have (with declarations sketched in)
entity tb
port (...
sdo : in std_logic;
sdi : out std_logic;
... );
end tb;
architecture foobar of tb is
signal sda : std_logic;
component dac_model
port (...
sda : inout std_logic;
... );
end component;
begin
DAC_BUFFER_MODEL : process (sdo, sda)
begin
if (sdo = '0') then
sda <= '0';
else
sda <= 'H';
end if;
--
-- The pin back to the FPGA should always be whatever is on sda
--
sdi <= sda;
end process;
my_dac : dac_model
port map (
sda => sda,
...);
So... is this going to do what I want it to do? Looks like I assign
sda a weak high if sdo is not low. I can make sure that the dac_model
treats sda properly (either 1, 0, or Z). I just hope that H will
resolve to 1 when it matters. I've spent most of my time in RTL and
have never, ever used the other values of std_logic since they don't
exist inside an FPGA.
Since there's no proper tristate command, I'm not able to guess when
the FPGA wants to tristate the bus and when it just wants to signal a
'1'. However I know the interior of the FPGA is also not written to
worry about 'H's versus '1's so at some point it has to be resolved
into very discrete levels.
Writing this, I just had the thought that I need to do this in my
process. So instead of the sdi <= sda assignment, perhaps something
here that resolves everything into real values would be good. However
I'm not sure how to go about this other than a brute force case
statement like:
case sda is
when '1' => sdi <= '1';
when '0' => sdi <= '0';
when 'H' => sdi <= '1';
when ...
Etc. You get the picture. Surely there's a better way to do this.
Any ideas out there? Anyone seen this setup before? I'd draw a
picture, but Google Groups doesn't do fixed space text input so I only
have the faintest idea of how it'd look. Hopefully I described it
well enough.
Best regards,
Mark Norton