Your code simulates two multiplexers. These are actually asynchronous components. The fact that Verilog requires data1_temp
and data2_temp
to be declared as reg
's is a quirk of Verilog syntax and your choice of coding style, and doesn't mean these signals would be the outputs of storage elements in a physical implementation.
If you want to capture these values in actual registers, you need to add those explicitly:
reg [7:0] data1, data2;
always @(posedge someclock) begin
data1 <= data1_tmp;
data2 <= data2_tmp;
end
But I would like to know what this mini register file would be made of in hardware. Particularly, the 4x8 bit array consisting of k0,k1,k2,k3.
You haven't shown how these variables are assigned, so it's not possible to say how they are implemented. As your code showed, just declaring them as reg
doesn't guarantee they are implemented with actual storage elements. If you assign them inside a block that begins always @(posedge clk)
then very likely they are flip-flops, but there are ways you could code them that would make them synthesize differently.
I thought when it came to registers and arrays like this, you need a clock to read out data, like RAM?
You need a clock to update a (physical) register. You can read it out at any time. For example:
wire [8:0] sum;
assign sum = k0 + k1;
is perfectly valid code. sum
will change whenever any of its inputs changes. If k0
and k1
are the outputs of flip-flops, their values will only change when there is a clock edge.
For another example, you could equally well describe your multiplexers with code like this:
reg [7:0] k0, k1, k2, k3;
wire [7:0] data1_tmp;
reg [1:0] reg1;
// k<n> and reg1 are assigned elsewhere.
assign data1_tmp = (reg1 == 0) ? k0 :
(reg1 == 1) ? k1 :
(reg1 == 2) ? k2 : k3;
how do I read from this tag_array and do the comparison all within the same clock cycle?
Let me repeat a key point for emphasis: You need to use a clock to assign a new value to a register (an actual hardware register or group of flip-flops). It's output is available at any time.
RAMs are different and how you access the contents of a RAM will depend on details of the type of RAM you use.
I got confused because frankly I don't know enough about memory hardware and how that's possible.
Another key strategy: When you are learning digital logic, I recommend you learn about the physical hardware first, and then work out or study how to simulate it in HDL second. So first, learn what a physical flip-flop is, then learn the standard Verilog methods of describing a flip-flop. Especially if you are trying to write HDL for synthesis, trying to write good code before you learn the capabilities of the underlying hardware will lead you down a lot of dead-end paths.
One possible cause: Synthesis is merging vga_g
, vga_b
, and vga_r
into a single net, because they are all equivalent. Then the translate step can't put them in different locations, because there's only one net in the synthesis output.
Solution 1. Explicitly instantiate your OBUFs.
OBUF obuf_vga_g ( .I ( on ), .O ( vga_g ) );
OBUF obuf_vga_b ( .I ( on ), .O ( vga_b ) );
OBUF obuf_vga_r ( .I ( on ), .O ( vga_r ) );
This makes it explicit in your code that the output nets are buffered from the on
signal and attached to output pins. Obviously the tool should already know these nets are connected to output pins because they're outputs of the top level module. Having to do this kind of thing is just one of the quirks of using a tool originally designed to describe logic for the different purpose of designing logic.
Solution 2. Use constraints to eliminate merging of duplicate logic.
Depending on which synthesis tool you use, there should be a constraint available that you can attach to your vga_b
, etc, signals to prevent them being merged in the synthesis step. In Synplicity, I believe you would use syn_keep
to prevent removing redundant combinatorial logic.
As Apalopohapa noted in a comment, you might also need to turn on a flag to enable Synthesis to automatically generate the OBUFs you need. This should default to 'on', but it doesn't hurt to double-check it.
Best Answer
Check your compiler logs. You will almost certainly find something saying "Combinational loop removed" - the synthesis tools will not allow this unless you specifically tell it to preserve each as a separate LUT. Have a look at the post-fit netlist and see what the synthesizer is producing.
Oscillators are not good for FPGAs as depending on the length of the chain and propagation delays, you can easily get several hundred MHz if not GHz signals which can burn out the device with excessive switching currents.
Even if it does keep the loop, you will almost certainly get odd behaviour. The oscillator will toggle so fast and with so much jitter that you will violate the setup and hold times of your counter which will result in weird behaviour.
Then if you are comparing it with a clock (which is also not good) of 10MHz, that means the counter is going to get reset for 50ns in every 100. Because this oscillator and the external clock are both asynchronous with no synchronisation, you will end up again violating setup and hold times of the output register and cause it to go metastable 0 - who knows what it will output then.