Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

check for a value in a multidimensional 'array'

Status
Not open for further replies.

lh-

Member level 1
Joined
Oct 5, 2016
Messages
37
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
277
i'm writing verilog code vending machine. i have 4 'columns' for each product, each of which is a 2D array. i need to check if there are still products left, if so, return that product and shift the bits so that i have a 0 for the returned product. first a coin is inserted, then a column (i.e. the 2D array) is selected. how should i do the checking in if()? and what should i shift? i don't get how to do this since it's a 2D array. should i 'walk over' every element of the array? or what?


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
module vending_machine(vend,change,coin,column,clk,rst);
  output reg vend;
  output reg [2:0] change;
  
  input [2:0] coin;
  input clk;
  input rst;
  
  parameter IDLE=2'b0;
  parameter PROCESSING=2'b1;
  parameter VENDING=2'b10;
  
  parameter ONE=3'b1;
  parameter TWO=3'b10;
  parameter THREE=3'b11;
  parameter FOUR=3'b100;
  
  parameter COL_A=3'b1;
  parameter COL_B=3'b10;
  parameter COL_C=3'b11;
  parameter COL_D=3'b100;
  
  reg [3:0] A[0:4];
  reg [3:0] B[0:4];
  reg [3:0] C[0:4];
  reg [3:0] D[0:4];
  
  reg [1:0] state;
  reg [1:0] next_state;
  
  reg [1:0] column;
  
  integer i;
  
  always @(posedge rst) begin
    state=IDLE;
    coin=0;
    change=0;
    column=0;
    for(i=0; i<4; i=i+1) begin
      A[i]=4'b1111;
      B[i]=4'b1111;
      C[i]=4'b1111;
      D[i]=4'b1111;
    end
  end
  
  always @(posedge clk) begin
    case(state)
      IDLE: begin
        if(coin) begin
          next_state=PROCESSING;
        end
        else begin
          next_state=state;
        end
      end
      
      PROCESSING: begin
        case(coin)
          ONE: begin
            case(column)
              COL_A: begin
                if() begin vend=1; change=0; <shift> end
                else begin vend=0; change=coin; end
              end
              default: begin $display("err"); end
            endcase
          end

 
Last edited by a moderator:

This code isn't going to work.

I think you need to find a non-antiquated tutorial. It is the end of 2016 and Verilog 2001 came out over 15 year ago...you can use C style module port syntax...it works on every single tool I've used in the past 5+ years.

Your reset code should not be implemented in a separate always block this will likely result in multiple driver errors.

you never assign next_state to state, you have a always block running off of the posedge of rst (do you expect rst to be a clock?) Oh wait I see you've got a backward way of describing the two always block FSM (you are assigning the next_state register with the current state value, which isn't from a FF, this is completely backward from the standard naming conventions, better go reread you antiquated tutorial site). Opinions vary but I am on the side of don't do this, use a single process/always block FSM style. The best reason for using the two process/always style was ancient tools were really bad at extracting FSMs that were written in a single clocked process/always. But as it is now 2016 and there are no ancient versions of synopsys dc being used it won't be problem (back in the early 90's it was sometimes a problem in our VHDL FSM code, so we always used two process FSMs). Your FSM though doesn't comply with any known one/two/three process/always FSM style, so the synthesis will probably generate garbage.

$display is not synthesizable, so don't use it in your code.

Your always @ (posedge clk) begin is missing an end to finish off the always block. Easy to do with lousy formatting of code.

You have a missing endcase for the case(coin) statement.

- - - Updated - - -

Why do you need a 2D array for the product, it doesn't make sense to me.
I'm assuming the A, B, C, D are the products so why is there an array for each product (16 dispensable items per product)?
If you have four of each product you only need a 1D array for each product.

Maybe you were supposed to implement a 2D array of the_products:

Code Verilog - [expand]
1
2
reg [3:0]  the_products [0:3] // [3:0] => four of the product that can be bought,
                              // [0:3] => 4 total types of product (instead of A-D)

 

I had put a comment in the end of the code saying that this is just a part of the code in which I have a question, I guess that part got cut off by a moderator for some reason.

Anyways. The rst needs to work only once and since it's not okay to write an initial block in this level of description, I put in always block. Is there a better solution?

I have 4 products, each of which is a 2D array, 4x5, total of 20 products. So at first I fill it with 1's:
1111
1111
1111
1111
1111Sometimes you're on top of the world, stay humble. Sometimes you've hit a low, stay hopeful. #lokai
Then I need to 'take a product', say it's the first 1, and shift the 4 bits so the array becomes
0111
........
But how do I check which row isn't empty to take the product from that row?
 

Believe me, a good FSM diagram should be your first step. Then it can be easily implemented into Verilog.
 

I had put a comment in the end of the code saying that this is just a part of the code in which I have a question, I guess that part got cut off by a moderator for some reason.
No, I did not cut anything off I just changed your code tags to syntax tags to make your code easier to read. I think it's more likely you have issues with using cut and paste on your computer....highlighted text below.

Anyways. The rst needs to work only once and since it's not okay to write an initial block in this level of description, I put in always block. Is there a better solution?
A better solution!? How about using the STANDARD template for a resetable FF. Maybe you should go find the Altera and Xilinx documents on writing synthesizable code.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// asynchronous reset FF
always @ (posedge clk, posedge rst) begin
  if (rst) begin
    q <= 1'b0;
  end else begin
    q <= d;
  end
end
 
// synchronous reset FF
always @ (posedge clk) begin
  if (rst) begin
    q <= 1'b0;
  end else begin
    q <= d;
  end
end




I have 4 products, each of which is a 2D array, 4x5, total of 20 products. So at first I fill it with 1's:
1111
1111
1111
1111
1111Sometimes you're on top of the world, stay humble. Sometimes you've hit a low, stay hopeful. #lokai
Then I need to 'take a product', say it's the first 1, and shift the 4 bits so the array becomes
0111
........
But how do I check which row isn't empty to take the product from that row?
You keep using repeated nomenclature to describe multiple things, you need to use precise terminology. Or maybe you do mean that this dispenses only a single product type, e.g. Coke only and you are referring to 20 Cokes in the machine. Or do you mean there are 4 product types, e.g. Coke, RootBeer, Sprite, and DrPepper. Each of which there are 20 in the machine arranged as an array of 4x5, which are output one row at a time, i.e.
Code:
Coke
1111        1111        1111
1111        1111        1111
1111        1111        1111
1111        1111        0011
1111  buy1  0111  buy5  0000

Sprite
1111        1111        1111
1111        1111        1111
1111        1111        0111
1111        1111        0000
1111  buy2  0011  buy7  0000
If the bits are shifted right as product is bought
1111 => abcd => 0abc => 00ab ...
You only need to check if a row is currently 0 to decide when the next row should be used. This uses a priority encoder (nested if statements)
Code:
if (row[0] != 4'b0) begin
  row[0] <= {1'b0, row[0][3:1]}; // this is a right shift of one row of the array
end else if (row[1] != 4'b0) begin
  row[1] <=...
end else if (row[2] != 4'b0) begin
...
 
  • Like
Reactions: lh-

    lh-

    Points: 2
    Helpful Answer Positive Rating
A better solution!? How about using the STANDARD template for a resetable FF. Maybe you should go find the Altera and Xilinx documents on writing synthesizable code.

@lh- , Hear what they are telling you; the the right thing to do is to take advantage of templates provided by FPGA manufacturers, which have either the mealy or moore option, depending up your requirements. Doing this way you have also the advantage of having the FSM viewer tool working accordingly.
 

I don't know any of those, we don't do that in class
 

I don't know any of those, we don't do that in class

There is more to real world engineering than your class. The documents I was referring to are on Xilinx and Altera's websites and they describe the coding styles and templates for writing synthesizable code. Vendors are usually the first resource you go to when looking for answers on using their tools. They also usually have lots of recommendations (which you should seriously consider) to ensure success.
 

Okay, got it. I'll take a look at those.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top