![]() |
Correct way of writing a mux followed by a register
I've googled around but haven't seen a good generic and flexible way
of writing a mux followed by a synchronous output. I've come up with code that's correctly interpreted as a mux by synplify, but it's a bit sketchy. Can anyone please enlighten me as to the right way of doing this: The following seems to be accepted by synplify as a mux followed by a register, but it seems logically incorrect: constant : width := 16; signal wr_en : std_logic; signal addr : std_logic_vector(addr_width downto 0); signal addr_int : integer; .... addr_int <= conv_integer(addr); mux_and_reg : process (clk) begin if rising_edge(clk) then if wr_en ='1' then for i in 0 to log2(addr_width) loop if i = addr_int then data_out <= data_in((i+1)*width-1 downto i*width); end if; end loop; end if; end if; end process; I would expect the loop to get unrolled and something weird to happen relating to the assignment (something like catching only the last value of i). Plan B was to do this: mux_and_reg : process (clk) begin if rising_edge(clk) then if wr_en ='1' then data_out <= data_in((addr_int+1)*width-1 downto addr_int*width); end if; end if; end process; But this seems to infer shift registers, which makes sense. So what is the right way to get a mux followed by a register? All of the standard examples focus on a hard coded address width and a select statement. How do I do this with a flexible for-loop or for-generate? Thanks, Chris |
Re: Correct way of writing a mux followed by a register
Chris Maryan wrote:
> I've googled around but haven't seen a good generic and flexible way > of writing a mux followed by a synchronous output. I've come up with > code that's correctly interpreted as a mux by synplify, but it's a bit > sketchy. Can anyone please enlighten me as to the right way of doing > this Start with something specific and inflexible to get started. An if/then/else statement inside a synchronous process can infer a mux and a register. The question is, will this netlist in my head really do what I want? The process of trial and error synthesis is the long road to working code, especially if the full design is more than a mux and a register. It may work fine for simple cases, but only if I already know the correct answer in advance. I test and debug my code using simulation until all the waves and assertions works as I expect. Then, I usually run an rtl view in synthesis to see the logical schematic of the full entity and to check my design rules. > The following seems to be accepted by synplify as a mux followed by a > register, but it seems logically incorrect: So run a sim and find out for sure. -- Mike Treseler related examples: http://mysite.verizon.net/miketreseler/count_enable.pdf http://mysite.verizon.net/miketreseler/count_enable.vhd |
Re: Correct way of writing a mux followed by a register
On Oct 31, 3:48*pm, Mike Treseler <mtrese...@gmail.com> wrote:
> Chris Maryan wrote: > > I've googled around but haven't seen a good generic and flexible way > > of writing a mux followed by a synchronous output. I've come up with > > code that's correctly interpreted as a mux by synplify, but it's a bit > > sketchy. Can anyone please enlighten me as to the right way of doing > > this > > Start with something specific and inflexible to get started. > > An if/then/else statement inside a synchronous process > can infer a mux and a register. The question > is, will this netlist in my head really do what I want? > > The process of trial and error synthesis > is the long road to working code, especially > if the full design is more than a mux and a register. > It may work fine for simple cases, > but only if I already know the correct answer in advance. > > I test and debug my code using simulation > until all the waves and assertions works as I expect. > Then, I usually run an rtl view in synthesis > to see the logical schematic of the full entity > and to check my design rules. > > > The following seems to be accepted by synplify as a mux followed by a > > register, but it seems logically incorrect: > > So run a sim and find out for sure. > > * * -- Mike Treseler > > related examples:http://mysite.verizon.net/miketresel...unt_enable.vhd Thanks Mike. Actually, yes it simulates correctly, it just disagreed with my understanding of how for-> if works, which I suppose is the clarification I was looking for. My expectation looking at the code was that the loop would unroll to something like for ... loop if ... then ... code for i=0; end if; if ... then ... code for i = 1; end if; ... end loop; rather than: for ... loop if ... then ... code for i=0; elsif ... then ... code for i = 1; elsif ... ... end if; end loop; Which seems to be what it actually unrolls to. Chris |
Re: Correct way of writing a mux followed by a register
Chris Maryan wrote:
> Thanks Mike. Actually, yes it simulates correctly, it just disagreed > with my understanding of how for-> if works, which I suppose is the > clarification I was looking for. Yes, it was confusing, and in those cases, I either run a sim to figure it out, or, if I have time, pull a function out so I can read it. Like you said, it's sort of like n byte shifts per clock. I use my own 'push' function for things like this. -- Mike Treseler -------------------------------------------------- function sel ( choice : boolean; a, b : std_logic_vector) -- sel(false,a,b) = a return std_logic_vector is -- like the C lang: sel ? a:b begin if choice then return a; else return b; end if; end function sel; -------------------------------------------------- function push (slim : in std_logic_vector; wide : in std_logic_vector; left : in boolean := true) return std_logic_vector is -- push byte into word from left or right subtype slim_t is std_logic_vector(slim'length-1 downto 0); subtype wide_t is std_logic_vector(wide'length-1 downto 0); variable in_vec : slim_t := slim; variable out_vec : wide_t := wide; begin return(sel( choice => left, a => out_vec(out_vec'left - in_vec'length downto 0) & in_vec, b => in_vec & out_vec(out_vec'left downto in_vec'length)) ); end function push; -------------------------------------------------- |
Re: Correct way of writing a mux followed by a register
"Chris Maryan" <kmaryan@gmail.com> wrote in message news:b2ff3ece-781d-4b71-aebd-04fc4a2203ca@c2g2000pra.googlegroups.com... > Thanks Mike. Actually, yes it simulates correctly, it just disagreed > with my understanding of how for-> if works, which I suppose is the > clarification I was looking for. > > My expectation looking at the code was that the loop would unroll to > something like > for ... loop > if ... then > ... code for i=0; > end if; > if ... then > ... code for i = 1; > end if; > ... > end loop; > > rather than: > > for ... loop > if ... then > ... code for i=0; > elsif ... then > ... code for i = 1; > elsif ... > ... > end if; > end loop; Generally speaking a sequential series of if statements is the form for a priority encoder, and that is logically equivalent to the single if/elsif/elsif.../end if statement so really the two forms that you listed are logically identical. I'm guessing though that what you're trying to get across is that this could be implemented without the long nested if/else logic being generated in the synthesized design much like a decoder decodes addresses. To do that though one needs to have mutually exclusive conditions (which you do; i=0, i=1...) and describe the design in a way that the tool understands that they are mutually exclusive. While a smart synthesizer possibly 'could' see that the various 'if' conditions are actually all mutually exclusive, as you've found you can't count on that to occur. If you know some set of conditions are mutually exclusive, then you will be able to express that with a case statement. When you do so, you'll find that the logic does synthesize to what I think you were expecting. The converse of that is that if you can not express it as a case statement then the conditions are not reeeeeeeally mutually exclusive in spite of what you think you 'know' to be true. Kevin Jennings |
Re: Correct way of writing a mux followed by a register
On Nov 1, 6:44*am, "KJ" <kkjenni...@sbcglobal.net> wrote:
> "Chris Maryan" <kmar...@gmail.com> wrote in message > > news:b2ff3ece-781d-4b71-aebd-04fc4a2203ca@c2g2000pra.googlegroups.com... > > > > > > > Thanks Mike. Actually, yes it simulates correctly, it just disagreed > > with my understanding of how for-> if works, which I suppose is the > > clarification I was looking for. > > > My expectation looking at the code was that the loop would unroll to > > something like > > for ... loop > > * if ... then > > * * ... code for i=0; > > * end if; > > * if ... then > > * * ... code for i = 1; > > * end if; > > * ... > > end loop; > > > rather than: > > > for ... loop > > * if ... then > > * * ... code for i=0; > > * elsif ... then > > * * ... code for i = 1; > > * elsif ... > > * ... > > * end if; > > end loop; > > Generally speaking a sequential series of if statements is the form for a > priority encoder, and that is logically equivalent to the single > if/elsif/elsif.../end if statement so really the two forms that you listed > are logically identical. > > I'm guessing though that what you're trying to get across is that this could > be implemented without the long nested if/else logic being generated in the > synthesized design much like a decoder decodes addresses. *To do that though > one needs to have mutually exclusive conditions (which you do; i=0, i=1...) > and describe the design in a way that the tool understands that they are > mutually exclusive. *While a smart synthesizer possibly 'could' see that the > various 'if' conditions are actually all mutually exclusive, as you've found > you can't count on that to occur. *If you know some set of conditions are > mutually exclusive, then you will be able to express that with a case > statement. *When you do so, you'll find that the logic does synthesize to > what I think you were expecting. > > The converse of that is that if you can not express it as a case statement > then the conditions are not reeeeeeeally mutually exclusive in spite of what > you think you 'know' to be true. > > Kevin Jennings- Hide quoted text - > > - Show quoted text - Hi "for i in 0 to log2(addr_width) loop " Above line is should be for i in 0 to 2**(addr_width) loop for logically correct of functionality. Whatever you are trying to write it, it will infer priority encoder. I think simply using case statement for parallel mux should be fine. |
Re: Correct way of writing a mux followed by a register
On Nov 3, 6:30*am, sandeep <sandeepkumar....@gmail.com> wrote:
> On Nov 1, 6:44*am, "KJ" <kkjenni...@sbcglobal.net> wrote: > > > > > > > "Chris Maryan" <kmar...@gmail.com> wrote in message > > >news:b2ff3ece-781d-4b71-aebd-04fc4a2203ca@c2g2000pra.googlegroups.com... > > > > Thanks Mike. Actually, yes it simulates correctly, it just disagreed > > > with my understanding of how for-> if works, which I suppose is the > > > clarification I was looking for. > > > > My expectation looking at the code was that the loop would unroll to > > > something like > > > for ... loop > > > * if ... then > > > * * ... code for i=0; > > > * end if; > > > * if ... then > > > * * ... code for i = 1; > > > * end if; > > > * ... > > > end loop; > > > > rather than: > > > > for ... loop > > > * if ... then > > > * * ... code for i=0; > > > * elsif ... then > > > * * ... code for i = 1; > > > * elsif ... > > > * ... > > > * end if; > > > end loop; > > > Generally speaking a sequential series of if statements is the form for a > > priority encoder, and that is logically equivalent to the single > > if/elsif/elsif.../end if statement so really the two forms that you listed > > are logically identical. > > > I'm guessing though that what you're trying to get across is that this could > > be implemented without the long nested if/else logic being generated in the > > synthesized design much like a decoder decodes addresses. *To do that though > > one needs to have mutually exclusive conditions (which you do; i=0, i=1...) > > and describe the design in a way that the tool understands that they are > > mutually exclusive. *While a smart synthesizer possibly 'could' see that the > > various 'if' conditions are actually all mutually exclusive, as you've found > > you can't count on that to occur. *If you know some set of conditions are > > mutually exclusive, then you will be able to express that with a case > > statement. *When you do so, you'll find that the logic does synthesize to > > what I think you were expecting. > > > The converse of that is that if you can not express it as a case statement > > then the conditions are not reeeeeeeally mutually exclusive in spite of what > > you think you 'know' to be true. > > > Kevin Jennings- Hide quoted text - > > > - Show quoted text - > > Hi > "for i in 0 to log2(addr_width) loop " > Above line is should be > for i in 0 to 2**(addr_width) loop > for logically correct of functionality. > Whatever you are trying to write it, it will infer priority encoder. > I think simply using case statement for parallel mux should be fine.- Hide quoted text - > > - Show quoted text - Yes, that should have been 2**..., Careless typing on my part. Your comment brings to mind a question: - Can a case statement be used somehow with a for loop? (the key thing here is the generic driven dimensions of the mux) Despite all the examples of using generics for signal widths, etc. There's a shortage of examples out there of generating size-flexible structures. I'd love to see good examples of using loops for a generic sized mux, demux, encoder and decoder (both priority and perhaps more importantly, non-priority). Does anyone know of any good references that show this? Anyone care to share some easy to read code? Thanks, Chris |
Re: Correct way of writing a mux followed by a register
Chris Maryan wrote:
> Despite all the examples of using generics for signal widths, etc. > There's a shortage of examples out there of generating size-flexible > structures. The trick is to not only declare the dimensions, but subtypes that use those dimensions and registers that use those subtypes, like this: http://mysite.verizon.net/miketreseler/stack.vhd -- Mike Treseler |
Re: Correct way of writing a mux followed by a register
On Nov 3, 9:08*am, Chris Maryan <kmar...@gmail.com> wrote:
> > I'd love to see good examples of using loops for a generic > sized mux, demux, encoder and decoder (both priority and perhaps more > importantly, non-priority). Does anyone know of any good references > that show this? Anyone care to share some easy to read code? > I wouldn't use a loop for a mux. Instead I'd use the following which can be used as either a concurrent statement or inside a process. mux_out <= mux_data_in(to_integer(unsigned(mux_sel))); For a demux, for i in demux_out'range loop if (to_integer(unsigned(demux_sel)) = i) then demux_out(i) <= demux_in; else demux_out(i) <= (others => '0'); end if; end loop; KJ |
Re: Correct way of writing a mux followed by a register
On Nov 3, 11:34*am, KJ <kkjenni...@sbcglobal.net> wrote:
> On Nov 3, 9:08*am, Chris Maryan <kmar...@gmail.com> wrote: > > > > > I'd love to see good examples of using loops for a generic > > sized mux, demux, encoder and decoder (both priority and perhaps more > > importantly, non-priority). Does anyone know of any good references > > that show this? Anyone care to share some easy to read code? > > I wouldn't use a loop for a mux. *Instead I'd use the following which > can be used as either a concurrent statement or inside a process. > > mux_out <= mux_data_in(to_integer(unsigned(mux_sel))); > > For a demux, > for i in demux_out'range loop > * if (to_integer(unsigned(demux_sel)) = i) then > * * demux_out(i) <= demux_in; > * else > * * demux_out(i) <= (others => '0'); > * end if; > end loop; > > KJ Inside a process, how about just the shorter form (skipping the looping and the testing): demux_out <= (others => (others => '0')); demux_out(to_integer(unsigned(demux_sel)) <= demux_in; If the demux is a single bit, skip the nested others choice. Fully worked example below. - Kenn library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; package types is subtype byte is std_logic_vector(7 downto 0); type byte_array is array(integer range <>) of byte; end types; library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use work.types.all; entity demux is port ( demux_in : in byte; demux_sel: in std_logic_vector(3 downto 0); demux_out: out byte_array(0 to 15) ); end demux; architecture a of demux is begin -- a process(demux_in, demux_sel) begin demux_out <= (others => (others => '0')); demux_out(to_integer(unsigned(demux_sel))) <= demux_in; end process; end a; |
| All times are GMT. The time now is 07:22 PM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.