![]() |
|
|
|||||||
![]() |
VHDL - Bidirectional bus and virtual pins |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
I'm trying to write a microprossesor interface module for my project.
It's your basic 8-bit bus with separate address bits and read / write strobes. The function of this VHDL module will be to take the data from the bus and stuff it into various 8-bit registers to be used by the other modules in my project. Of course this happens when the action is a 'write'. On reads it will take the addressed register and put it out on the same 8-bit bus. Here is my problem: I've got over 128 bits of outputs from this module. The fitter complains that I don't have that many pins. Ok, no problem, I'll just set them up as virtual pins. However this setting is ignored by Quartus since all of those pins are technically bidirectional (remember I have to be able to write and read from them) and it doesn't allow bidirectional virtual pins. What can I do? Shannon Shannon Gomes |
|
|
|
|
#2 |
|
Posts: n/a
|
"Shannon Gomes" <> wrote in message news > I'm trying to write a microprossesor interface module for my project. > It's your basic 8-bit bus with separate address bits and read / write > strobes. > > The function of this VHDL module will be to take the data from the bus > and stuff it into various 8-bit registers to be used by the other > modules in my project. Of course this happens when the action is a > 'write'. On reads it will take the addressed register and put it out > on the same 8-bit bus. > > Here is my problem: I've got over 128 bits of outputs from this > module. The fitter complains that I don't have that many pins. Ok, > no problem, I'll just set them up as virtual pins. However this > setting is ignored by Quartus since all of those pins are technically > bidirectional (remember I have to be able to write and read from them) > and it doesn't allow bidirectional virtual pins. > > What can I do? > > Shannon KJ |
|
|
|
#3 |
|
Posts: n/a
|
"Shannon Gomes" <> wrote in message news > I'm trying to write a microprossesor interface module for my project. > It's your basic 8-bit bus with separate address bits and read / write > strobes. > > The function of this VHDL module will be to take the data from the bus > and stuff it into various 8-bit registers to be used by the other > modules in my project. Of course this happens when the action is a > 'write'. On reads it will take the addressed register and put it out > on the same 8-bit bus. > > Here is my problem: I've got over 128 bits of outputs from this > module. The fitter complains that I don't have that many pins. Ok, > no problem, I'll just set them up as virtual pins. However this > setting is ignored by Quartus since all of those pins are technically > bidirectional (remember I have to be able to write and read from them) > and it doesn't allow bidirectional virtual pins. > > What can I do? Write the equations that enable the 128 bits on to the 8 bits at the approriate time....you'll have to do it at some point. i.e. Data <= Reg1 when (Addr = 0) else Reg2 when (Addr = 1) else ..... Reg 128 when (Addr = 127) else (others => 'Z'); Kevin Jennings KJ |
|
|
|
#4 |
|
Posts: n/a
|
On Feb 3, 6:59 pm, "KJ" <kkjenni...@sbcglobal.net> wrote:
> "Shannon Gomes" <sgo...@sbcglobal.net> wrote in message > > news > > > > > I'm trying to write a microprossesor interface module for my project. > > It's your basic 8-bit bus with separate address bits and read / write > > strobes. > > > The function of this VHDL module will be to take the data from the bus > > and stuff it into various 8-bit registers to be used by the other > > modules in my project. Of course this happens when the action is a > > 'write'. On reads it will take the addressed register and put it out > > on the same 8-bit bus. > > > Here is my problem: I've got over 128 bits of outputs from this > > module. The fitter complains that I don't have that many pins. Ok, > > no problem, I'll just set them up as virtual pins. However this > > setting is ignored by Quartus since all of those pins are technically > > bidirectional (remember I have to be able to write and read from them) > > and it doesn't allow bidirectional virtual pins. > > > What can I do? > > Write the equations that enable the 128 bits on to the 8 bits at the > approriate time....you'll have to do it at some point. > > i.e. > Data <= Reg1 when (Addr = 0) else > Reg2 when (Addr = 1) else > ..... > Reg 128 when (Addr = 127) else (others => 'Z'); > > Kevin Jennings Ouch That's a lot of coding, and a lot of opportunity for typo's. Try this tri-state bus approach (most fpga synthesizers can or will convert internal tri-states to muxes automatically. reg_type is array (0 to 127) of std_logic_vector(data'range); signal reg: reg_type; for i in reg'range generate data <= reg(i) when (read_en = '1') and (addr = i), else (others => 'Z'); end generate; Or, if you want the literal mux-before-tristate instead: process (reg, addr) is variable data_tmp : std_logic_vector(data'range); begin for i in reg'range loop if addr = i then data_tmp := reg(i); end if; end loop; if read_en = '1' then data <= data_tmp; else data <= (others => 'Z'); end if; end process; Andy Andy |
|
|
|
#5 |
|
Posts: n/a
|
On Sun, 04 Feb 2007 00:59:34 GMT, "KJ" <>
wrote: > >"Shannon Gomes" <> wrote in message >news >> I'm trying to write a microprossesor interface module for my project. >> It's your basic 8-bit bus with separate address bits and read / write >> strobes. >> >> The function of this VHDL module will be to take the data from the bus >> and stuff it into various 8-bit registers to be used by the other >> modules in my project. Of course this happens when the action is a >> 'write'. On reads it will take the addressed register and put it out >> on the same 8-bit bus. >> >> Here is my problem: I've got over 128 bits of outputs from this >> module. The fitter complains that I don't have that many pins. Ok, >> no problem, I'll just set them up as virtual pins. However this >> setting is ignored by Quartus since all of those pins are technically >> bidirectional (remember I have to be able to write and read from them) >> and it doesn't allow bidirectional virtual pins. >> >> What can I do? > >Write the equations that enable the 128 bits on to the 8 bits at the >approriate time....you'll have to do it at some point. > >i.e. >Data <= Reg1 when (Addr = 0) else > Reg2 when (Addr = 1) else > ..... > Reg 128 when (Addr = 127) else (others => 'Z'); > >Kevin Jennings > I'm not sure how that would solve my problem. I think maybe I am doing something so wrong that no one knows how to answer my question. I'll try to restate the problem: I have a bunch of 8 bit registers in this module. They are all outputs to other modules that I have written but haven't linked together yet. These output registers are also read by this module itself. Hence they are INOUT registers. Since there are more register bits than there are pins, when I try to compile this module by itself, the fitter screams that it can't fit. I tried to make all of the INOUT bits "virtual pins" but Quartus says it is ignoring that assignment. I think it is ignoring that assignment since they are bidirectional pins. I'm getting the picture that you just can't have a design of this type compile stand alone. Shannon mevidinous_nospam@sbcglobal.net |
|
|
|
#6 |
|
Posts: n/a
|
When creating a register bank, you usually have read_only regs aswell.
And sometimes it's handy to be able to produce events from software to your modules using a "write_only" register, i.e. a SW write will just pulse the written outputs for a cycle. If you declare a type reg_def and a another type reg_defs as an array of reg def, you can obtain a generic regbank as follows: type reg_type is (read_write, read_only, write_only); type reg_def is record reg_addr : natural; reg_type : reg_type; end record reg_def; type reg_defs is array (natural range <>) of reg_def; constant my_regs : reg_defs := ((0, read_only), (16#21#, read_write)); -- type regs is array (my_regs'range) of std_logic_vector(7 downto 0); signal reg_bank : regs; in your read_reg process: for i in my_regs'range loop if rd = '1' and addr = my_regs(i).addr then data_out <= reg_bank(i); end if; end loop; in your write_reg process: for i in my_regs'range loop if my_regs(i).reg_type = write_only then reg_bank(i) <= (others => '0'); end if; -- pulsed if wr = '1' and addr = my_regs(i).addr then case my_regs(i).reg_type when read_only => null; -- can't write read_only reg when read_write | write_only => reg_bank(i) <= data_in; end case; end if; end loop; Now connect reg_bank to your ports to the modules. (Hope the above compiles, but you get the idea...) To (try to) answer your question interface in a top module, put keep attributes on all registers, then OR all output bits to one pin, and take all input bits from another pin? HTH /Pontus pontus.stenstrom@gmail.com |
|
|
|
#7 |
|
Posts: n/a
|
"Andy" <> wrote in message news: oups.com... > On Feb 3, 6:59 pm, "KJ" <kkjenni...@sbcglobal.net> wrote: >> "Shannon Gomes" <sgo...@sbcglobal.net> wrote in message >> >> news >> >> >> >> > I'm trying to write a microprossesor interface module for my project. >> > It's your basic 8-bit bus with separate address bits and read / write >> > strobes. >> >> > The function of this VHDL module will be to take the data from the bus >> > and stuff it into various 8-bit registers to be used by the other >> > modules in my project. Of course this happens when the action is a >> > 'write'. On reads it will take the addressed register and put it out >> > on the same 8-bit bus. <snip> >> >> Write the equations that enable the 128 bits on to the 8 bits at the >> approriate time....you'll have to do it at some point. >> >> i.e. >> Data <= Reg1 when (Addr = 0) else >> Reg2 when (Addr = 1) else >> ..... >> Reg 128 when (Addr = 127) else (others => 'Z'); >> >> Kevin Jennings > > Ouch That's a lot of coding, and a lot of opportunity for typo's. > > Try this tri-state bus approach (most fpga synthesizers can or will <snip> For someone who is simply trying (and having obvious trouble) implementing read/write registers what you've posted will fly far over the head....I prefered to keep it a tad more straightforward to the problem at hand in the interest of 'walk before you can run and run before you can fly' Kevin Jennings KJ |
|
|
|
#8 |
|
Posts: n/a
|
<> wrote in message news:... > On Sun, 04 Feb 2007 00:59:34 GMT, "KJ" <> > wrote: > >> >>"Shannon Gomes" <> wrote in message >>news >>> I'm trying to write a microprossesor interface module for my project. >>> It's your basic 8-bit bus with separate address bits and read / write >>> strobes. >>> >>> The function of this VHDL module will be to take the data from the bus >>> and stuff it into various 8-bit registers to be used by the other >>> modules in my project. Of course this happens when the action is a >>> 'write'. On reads it will take the addressed register and put it out >>> on the same 8-bit bus. >>> >>> Here is my problem: I've got over 128 bits of outputs from this >>> module. The fitter complains that I don't have that many pins. Ok, >>> no problem, I'll just set them up as virtual pins. However this >>> setting is ignored by Quartus since all of those pins are technically >>> bidirectional (remember I have to be able to write and read from them) >>> and it doesn't allow bidirectional virtual pins. >>> >>> What can I do? >> >>Write the equations that enable the 128 bits on to the 8 bits at the >>approriate time....you'll have to do it at some point. >> >>i.e. >>Data <= Reg1 when (Addr = 0) else >> Reg2 when (Addr = 1) else >> ..... >> Reg 128 when (Addr = 127) else (others => 'Z'); >> >>Kevin Jennings >> > > I'm not sure how that would solve my problem. I think maybe I am > doing something so wrong that no one knows how to answer my question. > > I'll try to restate the problem: > > I have a bunch of 8 bit registers in this module. They are all > outputs to other modules that I have written but haven't linked > together yet. These output registers are also read by this module > itself. Hence they are INOUT registers. That's fine, they don't need to be 'inouts', 'out' is all that is needed from the individual modules. The code that instantiates the modules (i.e. the top level) will connect up signals to these outputs (Reg1, Reg2, etc) on the port map for each of these modules. What I was trying to imply is that you have these signals already (Reg1, Reg2...etc.) and they are all 8 bits wide that are presumably outputs of your modules. All you're trying to do by making these readable from your processor port is to have a way to select one of these to output on the processor's data bus ('Data' in my example). I did have a bit of a problem in my first post (corrected below). The signal Data_int selects (based on the processor address bus) which of your 8 bit registers you want to read from. Then, if the processor is actually performing a read (i.e. Processor_Read = '1') then output Data_int on to the signal 'Data' which is the only 'inout' signal in the mix, if no read is being performed, then 'Data' is tri-stated. Signal 'Data' is the processor data bus which would also be connected up to your modules for writing to the ports inside those modules. Previously you indicated that you were able to get the processor bus connected appropriately so that you could write to all the modules, the only difficulty is in reading back. Data_int <= Reg1 when (Addr = 0) else Reg2 when (Addr = 1) else ..... Reg 128 when (Addr = 127); Data <= Data_int when (Processor_Read = '1') else (others => 'Z'); > > Since there are more register bits than there are pins, when I try to > compile this module by itself, the fitter screams that it can't fit. I > tried to make all of the INOUT bits "virtual pins" but Quartus says it > is ignoring that assignment. I think it is ignoring that assignment > since they are bidirectional pins. What you're missing is that the outputs of your various modules are NOT meant to be the outputs of your top level directly. The only time those outputs are meant to come out (as I understand it) is when the processor is reading from it. This means that what you're missing is the logic that selects the appropriate module output (the equation listed above for 'Data_int') and then the logic to enable that selected output on to the actual physical input/output pins of your top level ('Data'). Kevin Jennings KJ |
|
|
|
#9 |
|
Posts: n/a
|
Thanks for all the wonderful responses. I think we are getting close
to the solution. What I've decided to do is post some psuedo code to show what it is I'm trying to do: ENTITY xFace IS PORT ( Addr : IN STD_LOGIC_VECTOR(3 DOWNTO 0); Data : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0); nRead : IN STD_LOGIC; nWrite : IN STD_LOGIC; MClk : IN STD_LOGIC; -- These registers are outputs only for this module. When this module gets hooked -- with the others under another top-level then these "output ports" will be hooked -- to "input ports" of the other modules. REG_A : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); REG_B : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); REG_C : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); REG_D : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); REG_E : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); REG_F : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); ); END xFace; ARCHITECTURE behavioral OF xFace IS SIGNAL data_in : STD_LOGIC_VECTOR(7 DOWNTO 0); SIGNAL data_out : STD_LOGIC_VECTOR(7 DOWNTO 0); BEGIN data_in <= Data; Data <= data_out WHEN nRead = '0' ELSE (OTHERS => 'Z'); PROCESS (MClk, nWrite) BEGIN IF (MClk'EVENT AND MClk = '1') THEN IF (nWrite = '0') THEN CASE Addr IS WHEN "0" => REG_A <= data_in; WHEN "1" => REG_B <= data_in; WHEN "2" => REG_C <= data_in; WHEN "3" => REG_D(7 DOWNTO 0) <= data_in; WHEN "4" => REG_D(15 DOWNTO WHEN "5" => REG_D(23 DOWNTO 16) <= data_in; WHEN "6" => REG_D(31 DOWNTO 24) <= data_in; WHEN "7" => REG_E(7 DOWNTO 0) <= data_in; WHEN "8" => REG_E(15 DOWNTO WHEN "9" => REG_E(23 DOWNTO 16) <= data_in; WHEN "10" => REG_E(31 DOWNTO 24) <= data_in; WHEN "11" => REG_F(7 DOWNTO 0) <= data_in; WHEN "12" => REG_F(15 DOWNTO WHEN OTHERS => Ignore it; END CASE; ELSE IF (nRead = '0') THEN -- NOTE: These "reads" are not legal since REG_X is declared as "OUT" CASE Addr IS WHEN "0" => data_out <= REG_A; WHEN "1" => data_out <= REG_B; WHEN "2" => data_out <= REG_C; WHEN "3" => data_out <= REG_D(7 DOWNTO 0); WHEN "4" => data_out <= REG_D(15 DOWNTO WHEN "5" => data_out <= REG_D(23 DOWNTO 16); WHEN "6" => data_out <= REG_D(31 DOWNTO 24); WHEN "7" => data_out <= REG_E(7 DOWNTO 0); WHEN "8" => data_out <= REG_E(15 DOWNTO WHEN "9" => data_out <= REG_E(23 DOWNTO 16); WHEN "10" => data_out <= REG_E(31 DOWNTO 24); WHEN "11" => data_out <= REG_F(7 DOWNTO 0); WHEN "12" => data_out <= REG_F(15 DOWNTO WHEN OTHERS => data_out <= (OTHERS => '0'); END CASE; END IF; END IF; END PROCESS; END behavioral Thank you all for being so patient with a noob. Shannon Shannon |
|
|
|
#10 |
|
Posts: n/a
|
wrote:
> I have a bunch of 8 bit registers in this module. They are all > outputs to other modules that I have written but haven't linked > together yet. These output registers are also read by this module > itself. Hence they are INOUT registers. I agree with Kevin. There are tri-buffers on device *pins* but register outputs and inputs are just wires. There are no physical tri-buffers *inside* the fpga. As Andy said, synthesis can infer muxes from an inout description, but a description using separate read and write data matches the the actual fpga hardware. To a slave entity, read data is a port output. and write data is a port input. To a master entity, write data is a port output and read data is a port input. An internal slave entity might might contain a local bus like this. clock : in std_ulogic; reset : in std_ulogic; address : in std_logic_vector(adr_len_g-1 downto 0); writeData : in std_logic_vector(char_len_g-1 downto 0); write_stb : in std_ulogic; readData : out std_logic_vector(char_len_g-1 downto 0); read_stb : in std_ulogic; Search for "stb" in the reference design here http://home.comcast.net/~mike_treseler/ for an example of inferring IO registers locally. -- Mike Treseler Mike Treseler |
|