WooHoo!!!! - PortB - Clean Room Attempt
mindrobots
Posts: 6,506
EDIT: Thanks to a pointer from PIK33, IT LIVES!!!!!
On Monday I started looking at adding PortB on paper and Tuesday morning, I saw that PIK33 had already posted his PortB code. Yay for the community, boo for me!
So, I'm been pressing along with my intended changes and trying to get it to work without looking at his thread or his implementation - mostly for a learning exercise for me now than anything else. I'm sure his implementation is better than mine.
I've had all the code in and have been struggling with pin assignments and getting the portb pins to even show up as assignable. My latest problem is that I get this message when trying to compile.
In top.tdf I have this code:
In dig.v, I have this:
There may be a few otehr places I've added code. Basically, everyplace there was an io, I created an iob and where there was a pin_something, I created a pinB_something (I know rather a brute force approach).
No, I can't figure out why Quartus is picking on my pinB_in and not the original pin_in. Any ideas before I give up and go look at PIK33's code?
Thanks!
On Monday I started looking at adding PortB on paper and Tuesday morning, I saw that PIK33 had already posted his PortB code. Yay for the community, boo for me!
So, I'm been pressing along with my intended changes and trying to get it to work without looking at his thread or his implementation - mostly for a learning exercise for me now than anything else. I'm sure his implementation is better than mine.
I've had all the code in and have been struggling with pin assignments and getting the portb pins to even show up as assignable. My latest problem is that I get this message when trying to compile.
Error (287084): Symbolic name "pinB_in" is used but not defined as a group
In top.tdf I have this code:
pin [31..0] : tri; pinB [31..0] : tri; . . . . -- pins core.pin_in[] = io[]; pin[].in = core.pin_out[]; pin[].oe = core.pin_dir[]; io[] = pin[].out; -- PORTB pins core.pinB_in[] = iob[]; pinB[].in = core.pinB_out[]; pinB[].oe = core.pinB_dir[]; iob[] = pinB[].out;
In dig.v, I have this:
input [31:0] pin_in, // pin state inputs input [31:0] pinB_in, // pin state inputs - PORTB . . . // pins assign pin_out = outx[7] | outx[6] | outx[5] | outx[4] | outx[3] | outx[2] | outx[1] | outx[0]; assign pin_dir = dirx[7] | dirx[6] | dirx[5] | dirx[4] | dirx[3] | dirx[2] | dirx[1] | dirx[0]; assign pinB_out = outx[7] | outx[6] | outx[5] | outx[4] | outx[3] | outx[2] | outx[1] | outx[0]; assign pinB_dir = dirx[7] | dirx[6] | dirx[5] | dirx[4] | dirx[3] | dirx[2] | dirx[1] | dirx[0];In cog.v, I have this:
input [31:0] pin_in, // pins output [31:0] pin_out, output [31:0] pin_dir, input [31:0] pinB_in, // pins for PORTB output [31:0] pinB_out, output [31:0] pinB_dir . . . // pins assign pin_out = (outa | ctra_pin_out | ctrb_pin_out | vid_pin_out) & dira; assign pinB_out = (outb | ctra_pin_out | ctrb_pin_out | vid_pin_out) & dirb; assign pin_dir = dira; assign pinB_dir = dirb;
There may be a few otehr places I've added code. Basically, everyplace there was an io, I created an iob and where there was a pin_something, I created a pinB_something (I know rather a brute force approach).
No, I can't figure out why Quartus is picking on my pinB_in and not the original pin_in. Any ideas before I give up and go look at PIK33's code?
Thanks!
Comments
Now I have somethig better than only port B. A 32bit system bus for the Propeller. Tomorrow will try to connect and test all of this
Thanks! That was so (NOT) obvious!
No I am past that hurdle, so I need to do some pin decoding nadn assigning and then see if it works......I'm thinking it won't. :frown:
A system bus sounds like fun!
I just made a couple changes (forgot one spot in addition to the hint PIK33 provided) and now I have a 64 PIN (as soon as I map the last 7 someplace) Propeller!!! I'd have video but my iPhone battery is dead.
I still have to test and figure out the counter and video but it looks like basic I/O (or at least basic /O) is working.
Chip is right, this is addictively fun and at this point, I'm just hacking and still don't know what all it can do!
As a side note, the person that came up with Figure 3-8 and Figure 3-9 in the DE0-Nano User Manual should really be taken out into the wilderness and left with nothing but a map of the same quality as their figures. One by product of this should be better pin mapping to connector cheat sheet for us Nano owners.
I still haven't looked at PIK33's implementation yet. I'm going to stay in "clean room" mode until I try the counters and video.
Time to just sit back in the warm glow of my blinking PortA and Port B LEDs for a while!!
Nothing is very different or better in my implementation, I only didn't this
I think (test this!) this duplicates counters and video pins on portb. Maybe having portb with ctr and vid enabled is good but it need some additional work to configure these circuits
I used only assign pinb_out=outb&dirb which gave me "pure" port.
And then I even removed this "&dirb", so I have independen dirb and outb ports=64 bits of output, then 32 bits of inb input. You have only to connect dirb in the top file and remove this tristate buffer,
Then you have 96 bits of system bus. 32 bit data in/data out. Some higher dirb pins for R/~W and strobe, and then 28..30 bit of dirb as an address bus
The vast majority of code references a single pin at a time. Having all 32 in a single register has perilously little upside.
Instead, I'd suggest extending the architecture by adding 9 new instructions and defining the architecture to have 512 IO pins. The instructions are: IOSET, IOClr, IORead, IOWrite, IODirIN, IODirOut, IODir, IOWait0, IOWait1
These instructions each designate an IO pin through use of the existing source operand mechanisms. When the address form is used, only the nine LSBs of the addressed value are used, the others are ignored.
Some of the instructions have an implied operand that is either zero or one. Others use the contents of the Carry Flag.
IOSet - Pin := 1
IOClr - Pin := 0
IORead - Carry := Pin
IOWrite - Pin := Carry
IODirIn - Pindirection := In
IODirOut - Pindirection := Out
IODir - Pindirection := Carry
IOWait0 and IOWait1 stop subsequent execution until the pin designated by the source operand has the value indicated
Backwards compatibility with the use of INA, OUTA and DIRA is straightforward as are WaitPEQ and WaitPNE. GPIOs 0..31 have slightly richer capabilities because those operations allow simultaneous access to those 32 pins - but since there's no way to extend that in a general fashion, I don't see the benefit given that those 32 can be accessed simultaneously and that ought to be sufficient for applications that benefit from that capability.
The actual number of GPIOs becomes an implementation decision.
I'm looking forward to trying out your 9 new instructions and 512 I/O pins and see how they compare to the "perilous" 32 bit ports we've been using all these years.
Considering I have no verilog experience and really wasn't ready or able to modify any of the development tools to add instructions, I'm rather proud of my ability to pull off this now insignificant and pointless exercise. The majority of the PortB support is already built into the existing Propeller architecture which makes it a very economical way to add I/O pins regardless of how perilous their use may actually be. Thank you for bringing me back to reality and pointing out the "right' approach for increasing the number or I/O pins available to me for free with minimal implementation effort.
Also, feel free to open your open thread with your design ideas, contributions and accomplishments. I'm sure no one will mind testing you theories, suggesting the right way for you to implement your code an ultimately test your running verilog on an FPGA.
Thank you for your comments!
On the larger FPGAs (eg DE2-115 / -150) there's plenty of i/o, and each cog's Port B could actually be individual to each cog, for applications where that made sense. PortA could remain common. Just one way to achieve > 256 GPIO.
What code? ARM code, probably. That's because "one pin at a time" is about the only way to use the jumbled-up I/O on an ARM. The less the Propeller's I/O looks like the average ARM Cortex chip, the better.