First you need to declare your EncodingNumbers
. From the way you used it, I think you want it to be a memory:
reg [7:0] EncodingNumbers [7:0];
This makes EncodingNumbers
a memory file with 8 elements, and each of those elements is 8 bits wide. Because you assign to it in an always block, you need to make it a reg
.
Then, if you want writes to be clocked but reads to be asynchronous, you can do this:
// write operation
always @(posedge clk) begin
if (EncodingMode == 0) begin
EncodingNumbers[EncodingIndex] <= EncodingNumber ^ Masks[EncodingIndex];
end
end
// read operation
assign EncodingResult = EncodingMode == 1 ? EncodingNumbers[EncodingIndex] : 8'bX;
The main take-away is, each signal that you control needs to be either a wire or a reg. You need to handle reg's in procedural code (always blocks) and wires in continuous code (assign statements).
Also notice that you didn't define what EncodingResult
should be when EncodingMode
is 0, so I just made it undefined --- you should put something else there, like 1 or 0.
Also, be aware, especially when using memories, if you're coding for synthesis (if going to implement the code in real hardware like an FPGA), you need to be careful to code things in a way that the hardware can actually match your code. If the memories in your hardware aren't able to do an asynchronous read (which is very common in FPGAs), for example, you will either get an error in synthesis (which is not so bad) or your hardware behavior won't match what you simulated (potentially much worse if you're not aware of it).
It is important to remember that with Verilog you are describing hardware, not writing software. Modules are instances of hardware. They can't be called and they don't return a value.
You can't instantiate a module conditionally within an if statements (*), and you definitely can't instantiate them within procedural blocks. If you consider what such a statement would describe it becomes clear as to why not. With a module instantiation within an if statement you are basically saying:
If signal is high, make some hardware appear; otherwise delete the hardware.
FPGAs can't work like that. All hardware is described and fixed at synthesis.
Instead what you need to do is instantiate your hardware (in this case right shift module) not within the if statement or procedural block. Connect the output of that module to a wire. Now your hardware is always present, regardless of the control signals. So how do you make use of it conditionally?
This is quite simple. Within the if statement you can use your wire. If a condition is met assign the wire to whatever signal you are controlling. Otherwise assign some other signal.
wire module_output_wire;
...
always @ (...) begin
...
if (some_condition) begin
some_signal <= module_output_wire;
end else begin
some_signal <= something_else;
end
end
...
your_module (
.whatever(module_output_wire)
);
The reason this now works is because rather than trying to infer transient hardware, you are now inferring a simple multiplexer. The inputs to the multiplexer are the module_output_wire
and something_else
, the select signal is some_condition
, and the output of the multiplexer is some_signal
. The hardware always exists, but you don't always need to use the output value.
As an alternative, you could make your right shift code a function. A function in Verilog can be called in the way you show on the commented out line in your code. In the case of the function you are inferring hardware that is always there and the output of the hardware is a wire (the return value of the function) which you can then use in an always block.
(*) With the exception of in Verilog 2001 Generate statements, but in that case the condition is known at compile time, it doesn't depend on the value of a signal.
Best Answer
You can't. A case statement should always be in an
always
orinitial
block.You have two choices if you don't want to use ternary conditionals. The first is use an always block which doesn't have edge sensitivity as shown below. This does not infer registers (that's not what declare the signal of
reg
type means), it infers a multiplexer with constant assignment - as there is no clock, so there is no register, the*
simply means any input change.Alternatively specifically infer a ROM or multiplexer depending on what your input signals are (possibly instantiate a module of one). If the inputs are constants (like parameters), then your case simply infers a ROM. If the inputs are nets, then your code infers a multiplexer.