0
\$\begingroup\$

I wrote a verilog code for a 4 by 9 bit register:

module reg_file(input rst,
            input clk,
            input wr_en,
            input rd_en,
            input [1:0]rd0_addr,
            input [1:0]rd1_addr,
            input [1:0]wr_addr,
            input [8:0]wr_data,
            output reg [8:0]rd0_data,
            output reg [8:0]rd1_data);

    reg [8:0]mem[3:0];
    integer i;

    always @(posedge rst or negedge clk)
    begin
        if (rst) begin
            for (i=0; i<4; i=i+1)
                mem[i]=0;
        end
        else if (wr_en) begin
            mem[wr_addr]=wr_data;
        end
        else (rd_en) begin
            assign rd0_data = mem[rd0_addr];
            assign rd1_data = mem[rd1_addr];
        end
    end
endmodule

but using iverilog to check if there are any issues, it says:

26: syntax error
27: Syntax in assignment statement l-value.
30: syntax error

I can't seem to figure out why I'm getting these errors, can anyone help?

I also need to find test vectors to test every possible outcome of the register file, does anyone have any suggestions on the best way to do that?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Those numbers at the front of the error messages are line numbers. Open your verilog file in a text editor that displays line numbers, and figure out where they are.

One problem I noticed was on the line:

else (rd_en) begin

You can't have a condition after else without another if keyword.

else if (rd_en) begin
\$\endgroup\$
5
  • \$\begingroup\$ When I do that I get the error "Assertion failed: (number_is_immediate(rword_idx, IMM_WID, 0)), function force_link_rval, file vvp_process.c, line 1256. sh: line 1: 14947 Done /opt/local/lib/ivl/ivlpp -L -F"/tmp/ivrlg2ef8b647" -f"/tmp/ivrlgef8b647" -p"/tmp/ivrlief8b647" 14948 Abort trap: 6 | /opt/local/lib/ivl/ivl -C"/tmp/ivrlhef8b647" -C"/opt/local/lib/ivl/vvp.conf" -- - tmp/cZpPzn/a.out:61: syntax error" \$\endgroup\$
    – dms94
    Feb 15, 2016 at 21:03
  • \$\begingroup\$ Doesn't mean much to me except that there is still a syntax error (perhaps in a generated file?). You could try removing almost all of the code in your file and adding it incrementally to see if the failure is related to a specific part of your code. \$\endgroup\$
    – Justin
    Feb 15, 2016 at 21:07
  • \$\begingroup\$ I did that and it was an issue with the assign statements, I took them out and it worked \$\endgroup\$
    – dms94
    Feb 15, 2016 at 21:13
  • \$\begingroup\$ Do you have any suggestions on how I would make test vectors for this? \$\endgroup\$
    – dms94
    Feb 15, 2016 at 21:18
  • \$\begingroup\$ Sorry, I don't really have a good answer. Please ask it as a new question to get more people looking at it. We usually try to have one real question per question so that they can be handled/answered separately. That being said, you need to add some detail about what your requirements are for the test vectors. Did your instructor just say "make some test vectors", and if so, what has he/she taught you about test vectors in class? Just some thoughts about what needs to be in a new question. \$\endgroup\$
    – Justin
    Feb 15, 2016 at 21:38
1
\$\begingroup\$

Afaics there are three problems with that verilog code.

  1. there is a missing if before (rd_en), as @Justin pointed out.

  2. the assign statements within the always blocks are bogus. (There is something called procedural continuous assignments and the syntax you are using here is such a procedural continuous assignment, but it is pretty sure that you did not mean that.)

  3. you are using blocking assignments in a clocked always block, which means that this code will experience race conditions in simulation. See e.g. this paper for details. In this case assignments to the same variable are exclusive anyways, so simply changing = to <= fixes this issue:

    module reg_file(input rst,
                input clk,
                input wr_en,
                input rd_en,
                input [1:0] rd0_addr,
                input [1:0] rd1_addr,
                input [1:0] wr_addr,
                input [8:0] wr_data,
                output reg [8:0] rd0_data,
                output reg [8:0] rd1_data);
    
        reg [8:0] mem [3:0];
        integer i;
    
        always @(posedge rst or negedge clk)
        begin
            if (rst) begin
                for (i=0; i<4; i=i+1)
                    mem[i] <= 0;
            end
            else if (wr_en) begin
                mem[wr_addr] <= wr_data;
            end
            else if (rd_en) begin
                rd0_data <= mem[rd0_addr];
                rd1_data <= mem[rd1_addr];
            end
        end
    endmodule
    

PS: Not a real issue for memories that are only 4 words deep, but for most FPGA architectures resetting of memories will inhibit instantiation of dedicated memory resources and yield a much larger synthesis result.

PPS: posedge rst or negedge clk is very unusual (but it is still valid Verilog of course). Are you sure you don't mean posedge clk or negedge rst?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.