From what it seems like, uart and usb are just two different ways of digital communication so it seems like if you just program a micro controller to accept uart through a couple io pins and put out usb in a couple other pins you could make a uart to usb bridge without buying anything. Kind of like translating languages. Is that how it works? Am I missing something? I am using a pic16f84a.
Any USB to UART bridge IC that you see in the market is already an MCU that has permanently committed firmware (may be in Flash or ROM). These also typically have dedicated UART and USB peripheral block on the chip. Using pure software to implement UARTs and USB line level protocol severely limits speed possibilities and would generally not be practical.
Many of the more modern day MCUs that have on board USB controller peripherals will have available App Notes and reference code that shows how to build a USB UART bridge. In some cases this just becomes a part of a much larger application that runs on the MCU. In particular if you have some 200MHz 32-bit MCU this becomes very practical to even support an RTOS and task processing for an application in addition to the bridge functionality.
Note: An MCU operating in this manner as a bridge is referred to as a USB CDC class device.
if you just program a micro controller to accept uart through a couple io pins and put out usb in a couple other pins you could make a uart to usb bridge without buying anything. Kind of like translating languages. Is that how it works?
Not really. From high theoretical computer-science standpoint, from a view of 20,000 feet, it might look that way. However, in reality it is quite different.
The UART is a primitive serial transfer protocol, START+eight-bit-toggling+STOP, no structures, addresses, data correction nor acknowledgement. Sent and hope that other receiver will catch it. At most a LF is expected back. But one can call it a "UART packet".
The basic USB requires to follow a strict protocol for exchange of highly-structured data, that are arranged in "packets". USB packets have SYNC, Packet ID, DATA, CRC, and EOP. The PID-DATA+CRC are encoded in a special way to maintain a balanced +-signal, to avoid the data lines to stay in one state for too long, unlike in UART. Classic USB uses NRZI encoding with "bit stuffing".
The packet exchange requires certain order called "transaction", which usually includes SETUP phase with ADDRESS, DATA phase, and USB device must respond back with some packet acknowledging correctness of received data. So typically it takes three individual packets for a "transaction".
Then the USB transactions are arranged into "transfers", which include SETUP, DATA (might be many DATA packets), and acknowledge packets for each DATA, both ways. There are also CONTROL transfers, which have SETUP stage, DATA stage, and STATUS stage, so typical control transfer (to set or get some parameter from device) takes 9 individual USB packets, each having SYNC-PID/ADDRESS-CRC_EOP structure.
More, responses to incoming packets are time-limited to under 1.7 us response time, so not many MCU are able to decode a packet, verify its checksum, and respond back under 2 microseconds. Therefore the support for USB protocol is usually implemented in hardware, at least the time-critical parts. This is called USB SIE - Serial Interface Engine. While the order and generation of transfers is a responsibility of USB HOST and is not your concern, devices must obey the SIE rules, decode all packets, and respond properly in time.
A USB device becomes functional after a process called "enumeration", which includes reading device capabilities and functional purpose (aka "device descriptors"), receiving individual USB address, selecting/initializing "device configuration". This enumeration typically takes a dozen of control transfers, and it must occur before any bridge between USB DATA and UART DATA can be established.
Given this brief "crush" course in USB, you now decide if you can implement this SIE ("put out usb in a couple other pins") in your PIC16 micro-controller.