I'm trying to understand what the following bit of behavioral code, what kind of hardware it turns into:
reg [7:0] k0, k1, k2, k3;
reg [7:0] data1_tmp, data2_tmp;
// Asynchronously read data from two registers
always @(*)
begin
case (reg1)
0: data1_tmp = k0;
1: data1_tmp = k1;
2: data1_tmp = k2;
3: data1_tmp = k3;
endcase
case (reg2)
0: data2_tmp = k0;
1: data2_tmp = k1;
2: data2_tmp = k2;
3: data2_tmp = k3;
endcase
end
Logically I understand what it's doing. But I would like to know what this mini register file would be made of in hardware. Particularly, the 4×8 bit array consisting of k0,k1,k2,k3. I thought when it came to registers and arrays like this, you need a clock to read out data, like RAM?
See I'm having a conceptual problem designing a simple verilog cache module. I have a data array containing all my tags like so:
reg [NUM_TAG_BITS-1:0] tag_array[NUM_BLOCKS-1:0]
And I have a wire "line_select" (from my input PC). What I want to do is retrieve tag_array[line_select] and then put it into a comparator with the tag from my PC to see if I have a hit.
But I thought whenever I access tag_array, I need to be inside "always @ (posedge clk)" code. Then I got stuck: how do I read from this tag_array and do the comparison all within the same clock cycle? So I found the above code online saying you can read from regs asynchronously, then I got confused because frankly I don't know enough about memory hardware and how that's possible.
Thanks a lot for any help!
Best Answer
Your code simulates two multiplexers. These are actually asynchronous components. The fact that Verilog requires
data1_temp
anddata2_temp
to be declared asreg
'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:
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 beginsalways @(posedge clk)
then very likely they are flip-flops, but there are ways you could code them that would make them synthesize differently.You need a clock to update a (physical) register. You can read it out at any time. For example:
is perfectly valid code.
sum
will change whenever any of its inputs changes. Ifk0
andk1
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:
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.
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.