Address decoder - Page 1
Forum section: electronics / general

author: josuah
author_rank: Regular Contributor
timestamp: April 22, 2022, 04:13:08 pm
content: Hello engineers and hobbyists!This seems like a frequent use-case: turning an address into a bit saying "it's my turn" or "ignore the data".For that, just an equal sign works:Code:if (address == 0x3F)But if we look at things from the opposite angle, it might be seen as turning an address into an array of "clock select" signal, one bit per peripheral. Like it is on SPI, with an "enable" signal (en0, en1, en2...).Code:┌─────┐│ t0 │┌───────en0 ││ ┌───data │┌───────────┐ │ │ └─────┘│ decoder │ │ │ ┌─────┐│ en0───┘ │ │ t1 │─sel en1───────────en1 │─data en2───┐ ├───data ││ │ │ │ └─────┘│ data───│───┤ ┌─────┐└───────────┘ │ │ │ t2 │└───────en2 │└───data │└─────┘This would permit me to write modules with all the "bus" architecture out of the way.For instance (I do not know VHDL yet, so it is Verilog): usinghttps://stackoverflow.com/questions/1378159/I could then make a batch of PWM channels in an array of CHANNELS instances:Code:wb_pwm_channel #(.BITS(BITS)) channel[CHANNELS-1:0] (.wb_clk_i(wb_clk_i),.wb_rst_i(wb_rst_i),.wb_dat_i(wb_dat_i[BITS-1:0]),.wb_stb_i(channel_sel),.pwm_counter(counter),.pwm_channel(pwm));Here, wb_* are some of the BUS signals (wishbone), pwm_* are used for the bus logic, and channel_sel would be an array of CHANNELS bits, and as per the Verilog syntax, each bits would get dispatched to one instance making it its "enable" signal.I am much a beginner, yet I did not come across the name of the well-known method for doing this.Any hint?More lengthy description of the problem:https://www.josuah.net/blog/1650637875/

author: Bassman59
author_rank: Super Contributor
timestamp: April 22, 2022, 05:19:49 pm
content: Quote from: josuah on April 22, 2022, 04:13:08 pmIt's a selector. (If it was aSelecter, it would be a ska band.)The idea is that you decode the address, gate it with a write enable, and if the address matches while write enable is asserted, you assert your enable strobe.So for each "thing" you want to control, you have a bit of logic with an address comparator and the write enable gate.I'm not sure why this is complicated?

author: hamster_nz
author_rank: Super Contributor
timestamp: April 22, 2022, 08:52:24 pm
content: With this sort of decoding it can sometimes pay to be mindful of the underlying FPGA architecture. If you are on a "LUT6" architecture, it is most efficient to decode 6 bits at a time, as decoding more will require the use of additional lookup tables and or logic elements, and possibly slow the design.So when I make register banks for a peripheral I tend to give them 16 addresses, even if they only need a handful. That way the decoding of "write enable" for an individual register will be the the lowest 4 address bits, the "enable signal" and the "write enable" for the peripheral.It's not a hard or fast rule, but it does help me make sure that I'm not using excessive resources in the decoding that could be used elsewhere, or slowing things down.It also is one less somewhat arbitrary design decision to make... how much register address space should a peripheral have? 16 addresses (unless it needs more).It is somewhat pointless have less, as it will not save logic resources, nor will it be any faster.

author: josuah
author_rank: Regular Contributor
timestamp: April 23, 2022, 01:12:06 am
content: Much grateful of that precious feedback.(listenning at "On My Radio by Selecter" as I read through the answers)QuoteWhat a searchable name we got there! Search Engine time!QuoteNot sure it is coplicated. I identified athing, and liked to put a name on it.The rest is choosing the appropriate HDL syntax and coming-up with a nice gateware. Talking of which...QuoteThat introduces me to FPGA Architecture! I had no idea that there was some kind of "ARMv6" vs "ARMv7" vs "AVR" vs RISC-V (woops! not much open-FPGA architecture yet...) for FPGA.QuoteI could have spent a stupid amount of time on simply choosing these numbers, and changing them over and over.Yes, that will help me too.I will update this thread when I get some result...

author: Someone
author_rank: Super Contributor
timestamp: April 23, 2022, 01:40:48 am
content: Quote from: josuah on April 22, 2022, 04:13:08 pmIts high level code (HDL), there is not only one way to do it. Everything is specific in the context and rarely will people agree on what is the best way to do it.Personally, I wouldn't break apart the decoding and the instantiations unless they were non-uniform addresses (even then I'd probably keep them together)genvar j;generatefor (j=0; j<8; j=j+1)beginwb_pwm_channel #(.BITS(BITS)) channel (.wb_clk_i(wb_clk_i),.wb_rst_i(wb_rst_i),.wb_dat_i(wb_dat_i[BITS-1:0]),.wb_stb_i(wb_stb_i && (wb_addr_i[3:0] == j)),.pwm_counter(counter),.pwm_channel(pwm));endendgenerate

author: josuah
author_rank: Regular Contributor
timestamp: April 23, 2022, 12:37:03 pm
content: It looks like Verilog (and most likely many other HDLs too) is having sort of a decoder operator: bitshifts.It converts 0b0011 into 0b1000, so with some of bit twiddling:Code:wb_pwm_channel #(.BITS(BITS)) channel[CHANNELS-1:0] (.wb_clk_i(wb_clk_i),.wb_rst_i(wb_rst_i),.wb_stb_i({ {CHANNELS-1{1'b0}}, wb_stb_i } << wb_adr_i),.wb_dat_i(wb_dat_i[BITS-1:0]),.pwm_counter(counter),.pwm_channel(pwm));There is padding here to make sure wb_stb_i gets a CHANNELS-long input (dispatched over the CHANNELS modules):{ {CHANNELS-1{1'b0}}, wb_stb_i }. SystemVerilog(CHANNELS-1)'(wb_stb_i)static cast (is that the name?) syntax would have made this more readable.That is shorter, but not more readable, and much less obvious at first glance, than using a generate block.I learned quite a few things, thank you all three.