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).
I am not sure why you need a special option, the use of memories are pretty standard for use inside modules. Unless you are trying to imply a special low area/power cell similar to a ram.
For a standard memory it is just the same as having multiple regs. memory does not imply RAM the same way reg does not automatically imply flip-flop.
The 'memory.list' is a plain text file which contains the values which you want to load in to the memory, this is not required if you just wanted to reset the memory and have every element at 0.
memory.list should look like :
//Comments are allowed
1100_1100 // This is first address i.e 8'h00
1010_1010 // This is second address i.e 8'h01
@ 55 // Jump to new address 8'h55
0101_1010 // This is address 8'h55
0110_1001 // This is address 8'h56
The use of the file would then follow :
module memory();
reg [7:0] my_memory [0:255];
initial begin
$readmemh("memory.list", my_memory);
end
endmodule
alternatively :
module memory();
reg [7:0] my_memory [0:255];
integer i;
initial begin
for( i=0; i<256; i=i+1) //Can be statically unrolled
my_memory[i] = 8'h00 ;
end
endmodule
If using as a bank of flip-flops with async-reset:
module memory(
input clk,
input rst_n,
input [7:0] addr_wr,
input [7:0] data_wr
);
reg [7:0] my_memory [0:255];
integer i;
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
for( i=0; i<256; i=i+1) //Can be statically unrolled
my_memory[i] <= 8'h00 ;
end
else begin
my_memory[addr_wr] <= data_wr ;
end
end
endmodule
Best Answer
That syntax is called an indexed part-select. The first term is the bit offset and the second term is the width. It allows you to specify a variable for the offset, but the width must be constant.
Example from the SystemVerilog 2012 LRM: