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.
Best Answer
This is an important thing to understand. Verilog is a hardware description language, which means that what you are doing is not writing code the accesses 2D arrays and such, you are writing code that describes what hardware is required. In something like C (a procedural language), initialising an array is something that is done at run time - the CPU copies the contents of the array from the program memory into RAM and can then use it. However here you don't have that step.
Furthermore, the syntax you are trying to use is something from C, not Verilog. In fact in Verilog,
{}
means concatenation. So in essence what you are doing is concatenating ten 16bit values into a single 160bit vector. You are then trying to assign it as the initialisation value to a RAM which is not the same size - how does a 1x160 vector fit into a 10x16bit memory?Also note that your register is declared the wrong size - you say you want it 16bits, but you've made each one 17bits ([16:0] = 17b).
You have two options to consider.
Option 1
The first choice is to split things up a bit. Rather than trying to do everything in one go, consider what your hardware is doing. In essence what you have is not a RAM, but rather sixteen 10bit circular shift registers. They all work in sync with each other, yes, but they are effectively sixteen copies of the same hardware, so lets work with that. How do we make sixteen identical copies of something? Two options, make a module and instantiate it sixteen times, or more simply use something called a
generate
loop - it's basically a for loop that instantiates multiple copies of hardware. Lets use the second option.Option 2
Having said all of the above, actually in your case you don't really need to split things up, but I wanted to present the option first to give you a sense of what is going on under the hood so to speak, and give you some useful info for future work.
We can actually use one of the things I introduced in the other example to initialise the memory directly, the so called
initial
block. This allows you to do various things "at the beginning". Remember how I said that for a C program initialising the array is done at run time. Well in Verilog it is possible to do something similar but at synthesis. In other words, we can initialise the array by telling the synthesizer what the default value for each register (power on value) will be.For multidimensional groups of registers, like memories, we can define an initial block which can do very similar things to your always block. In this case for loops.