The code you show is essentially a priority encoder.
That is, it has an input of many signals, and its output indicates which of those signals is set, giving priority to the left-most set signal if more than one is set.
However, I see conflicting definitions of the standard behavior for this circuit in the two places I checked.
According to Wikipedia, the standard priority encoder numbers its inputs from 1. That is, if the least significant input bit is set, it outputs 1, not 0. The Wikipedia priority encoder outputs 0 when none of the input bits are set.
Xilinx's XST User Guide (p. 80), however, defines a priority encoder closer to what you coded. The inputs are numbered from 0, so when the input's lsb is set it gives a 0 output. However, the Xilinx definition gives no spec for the output when all input bits are clear (Your code will output 3'd7).
The Xilinx user guide, of course, will determine what the Xilinx synthesis software is expecting. The main point is that a special directive (*priority_extract ="force"*)
is required for XST to recognize this structure and generate optimal synthesis results.
Here's Xilinx's recommended form for an 8-to-3 priority encoder:
(* priority_extract="force" *)
module v_priority_encoder_1 (sel, code);
input [7:0] sel;
output [2:0] code;
reg [2:0] code;
always @(sel)
begin
if (sel[0]) code = 3’b000;
else if (sel[1]) code = 3’b001;
else if (sel[2]) code = 3’b010;
else if (sel[3]) code = 3’b011;
else if (sel[4]) code = 3’b100;
else if (sel[5]) code = 3’b101;
else if (sel[6]) code = 3’b110;
else if (sel[7]) code = 3’b111;
else code = 3’bxxx;
end
endmodule
If you can rearrange your surrounding logic to let you use Xilinx's recommended coding style, that's probably the best way to get a better result.
I think you can get this by instantiating the Xilinx encoder module with
v_priority_encoder_1 pe_inst (.sel({~|{RL[6:0]}, RL[6:0]}), .code(rlever));
I've nor'ed together all bits of RL[6:0]
to get an 8th input bit that will trigger the 3'b111 output when all RL bits are low.
For the llever
logic, you can probably reduce the resource usage by making a modified encoder module, following the Xilinx template, but requiring only 7 input bits (your 6 bits of LL
plus an additional bit that goes high when the other 6 are all low).
Using this template assumes the version of ISE you have is using the XST synthesis engine. It seems like they change synthesis tools on every major rev of ISE, so check that the document I linked actually corresponds to your version of ISE. If not, check the recommended style in your documentation to see what your tool expects.
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
Verilog does not support two dimensional arrays or unpacked arrays as ports; SystemVerilog does. Verilog does support a packed array (also referred to as a vector) as a port.
For verilog, you need to pass the index. Examples:
.packet_size(packet_size_temp[0]),
or.packet_size(packet_size_temp[reg_or_wire_of_index]),
.If you need to pass the whole array, then you will need to flatten it to one big vector and slice it on the other side:
Review on
+:
stackoverflow: Indexing vectors and arrays with +: and What is +: and -:?Enabling SystemVerilog is alternative, it does support arrayed ports. To do so, it is recommend the change the file extension from
.v
to.sv
. Most simulators and synthesizers will properly parse the file with only the correct extinction. Another approach is to set a compiler flag which is tool dependent (usually -sv or -sverilog), but this will typically force all Verilog files to be treated as SystemVerilog which may have naming conflicts with SystemVerilog keywords.