Search code examples
verilogxilinx-ise

How to execute task concurrently with other statements in an always block?


I am writing code for 8*4 RAM in Verilog. For each binary cell of memory, I am using an SR flip-flop. Initially, each cell is assigned 1'bx. The logic seems to be correct, but the output isn't. It is probably because statements are not getting executed concurrently. Can anyone suggest how can I get the task SRFlipFlop to get executed concurrently with other statements?

module memory(addr, read_data, rw, write_data, clk);
// read_data is the data read
// rw specifies read or write operation. 1 for read and 0 for write
// write data is the data to be written
// addr is the address to be written or read    

task SRFlipFlop;
input d,r,s,clk; // d is the value initially stored
output q;  
begin
case({s,r})
{1'b0,1'b0}: q<=d;
{1'b0,1'b1}: q<=1'b0;
{1'b1,1'b0}: q<=1'b1;
{1'b1,1'b1}: q<=1'bx;
endcase
end
endtask

task decoder;     // a 3 to 8 line decoder
input [2:0] A;
input E;
output [7:0] D;
if (!E)
    D <= 16'b0000000000000000;
else
    begin
        case (A)
            3'b000 : D <= 8'b00000001;
            3'b001 : D <= 8'b00000010;
            3'b010 : D <= 8'b00000100;
            3'b011 : D <= 8'b00001000;
            3'b100 : D <= 8'b00010000;
            3'b101 : D <= 8'b00100000;
            3'b110 : D <= 8'b01000000;
            3'b111 : D <= 8'b10000000;
        endcase
    end
endtask


output reg [3:0] read_data;
input [3:0] write_data;
input [2:0] addr;
input rw, clk;
reg [3:0] memory [7:0];
reg [3:0] r [7:0];
reg [3:0] s [7:0];
reg [3:0] intermediate;
reg [3:0] select [7:0];
reg [7:0] out;
reg [7:0] out1;
integer i,j,k,l;
initial 
  begin
    for (i = 0; i <= 7; i=i+1) 
        begin
            for (j = 0; j <= 3; j=j+1) 
                begin
                 memory[i][j] = 1'bx;
                 r[i][j] = 1'b0;
                 s[i][j] = 1'b0;
                 select[i][j] = 1'b0;
                end
        end
  end
  always @(posedge clk)
  begin
    decoder(addr, 1'b1, out);
     for (i = 0; i <= 7; i=i+1)
        begin
            if (out[i] == 1'b1)
                begin
                for (j = 0; j <= 3; j=j+1)
                    begin
                        select[i][j] <= 1'b1;
                        s[i][j] <= write_data[j] & !rw & select[i][j];
                        r[i][j] <= !write_data[j] & !rw & select[i][j];
                        SRFlipFlop(memory[i][j],r[i][j],s[i][j],clk,intermediate);
                        memory[i][j] <= intermediate;
                        read_data[j] <= memory[i][j];
                    end
                end
        end
  end
endmodule

Solution

  • Your code style is very software-oriented. Personally I like to know how my code will look as a circuit, so instead of using nested for loops and tasks I will use modules and generate-loops to create my circuits.

    I have not been able to make your code work, but I suspect that the error is in the fact that s and r are not reset to zero on every iteration.

    I have created a functioning design here: http://www.edaplayground.com/x/Guc

    Instead of using the initial block to initialize values I have added an asynchronous reset.

    The SRFF-task has been converted to a module. A RAMblock module instantiates four SRFF-modules. 8 RAMblocks are instantiated in the memory module.

    I have converted your packed(reg [] a []) arrays into unpacked arrays(reg [][] a) to be able to perform bitwise operations on several bits without for-loops.

    If you have questions about the code, feel free to message me.

    Edit: Perhaps the most important thing to note in this design is that I separate the sequential circuitry from the combinatorial. This way it is much easier to control what should be updated on the posedge of clk and what should just be a combinatorial reaction to the changes performed at the posedge.