Independent inb and outb
pik33
Posts: 2,366
Maybe sometimes there is better to have input and output ports independent. Having Port B enabled I modified top like this:
Then, when sw[x] is on, led[x] glows. Not possible with bidir pins.And still, if I want a bidir pin on port B I can have it by simply adding a tristate buffer using inb[x], outb[x] and dirb[x].
--------- -- TOP -- --------- include "altpll.inc"; -- main clock pll, outputs 160MHz include "tim.inc"; -- clock generator, outputs 80MHz..20KHz cog clock, plus 2x CTRA/CTRB PLL simulator clock include "dig.inc"; -- digital core of P8X32A subdesign prop ( clock_50 : input; -- clock input inp_resn : input; -- reset pin io [31..0] : bidir; -- i/o pins outb [31..0] : output; -- i/o pins inb [31..0] : input; dirb [31..0] : output; ledg [7..0] : output; -- cog leds clkpll : output; clkcog : output; ) variable pll : altpll with ( pll_type = "enhanced", operation_mode = "normal", inclk0_input_frequency = 20000, -- 20000ps = 50MHz clk0_multiply_by = 24, clk0_divide_by = 5); clkgen : tim; core : dig; nres : dffe; pin [31..0] : tri; begin -- clocks pll.inclk[] = (gnd, clock_50); clkgen.clk = pll.clk[0]; clkgen.res = !inp_resn; clkgen.cfg[] = core.cfg[6..0]; core.clk_pll = clkgen.clk_pll; core.clk_cog = clkgen.clk_cog; clkpll = clkgen.clk_pll; clkcog = clkgen.clk_cog; -- reset nres.clk = clkgen.clk_cog; nres.d = inp_resn & !core.cfg[7]; core.nres = nres.q; -- pins core.pin_in[] = io[]; core.pin_inb[] = inb[]; pin[].in = core.pin_out[]; pin[].oe = core.pin_dir[]; outb[] = core.pin_outb[]; dirb[] = core.pin_dirb[]; io[] = pin[].out; -- cog leds ledg[] = core.cog_led[]; end;Then I connected inb to SWs, outb to LEDRs and run this in spin:
pub start dirb:=$FFFFFFFF repeat outb:=inb
Then, when sw[x] is on, led[x] glows. Not possible with bidir pins.And still, if I want a bidir pin on port B I can have it by simply adding a tristate buffer using inb[x], outb[x] and dirb[x].
Comments
Interesting idea, and makes sense on FPGA targets which tend to have shiploads of unused pins.
You could expand this some more, to avoid constraints of IP only.
Some uC split the OUTB, so write goes to the pins, and simple read gets the pin state.
This slight variance allows 32 io lines to map to one register.
The same rule can apply to INB, a write to that, can go to another 32 op register..
If you also want DataDir control of > 2 ports, then a double-write might be possible.
It's a little clunky, but preserves register space - the rule is a second write to the same address, goes to another destination. To reach that second location requires always write of two longs, so those pins are the set-and-forget types.
Using these expansion rules, a default part might have 64io, but an extended one can have 128io, or if they are not bi-dir, they can reach to 128o and 128i, which is getting up to the FPGA useful limits.