3 Replies Latest reply on Oct 4, 2020 9:14 PM by MoTa_728816

    Base Counter component (Verilog) example?

    JiSt_4468101

      I'm a relative noob to PSOC, and am trying to identify the simplest/best (leaning strongly toward simplest :-) approach to implementing a counter that can count up and down.  The 'Base Counter' verilog component outwardly looks like it might fit the bill (specifically, it's 'Clock and Direction' mode), but I can find no data sheet, documentation, code examples, etc for it.  (I've started picking my way through the .v file for it, but it's slow going for a noob.)

       

      Is there any type of code example for the use of this component?  If someone more experienced thinks this is not the simplest/best approach to implementing a counter that can count up and/or down, I'd be open to suggestions!

       

      I'm trying to implement a step/dir stepper driver, and would ideally like to use the counter value to keep track the motor's assumed position, as it is subsequently fed pos/neg steps by a PID process, if that helps add any clarity to what I'm trying to get to.  The other side of that is that I'd like it to sort of be a 'fire and forget' type of process - w/o the need for interrupts, continually calling the stepper routine, etc - so call a 'moveToPosition(p)' and/or 'moveSteps(s)' type of function, would set the counter's compare or period value, sets the direction needed to get there, and then the hardware drives the needed number of step pulses to get to the target position, w/o the firmware having to really be involved.  (I'm also open to suggestions on that type of process, if anyone has any to offer!)

       

      Oh, I'm working with a PSOC62 on the CY8CKIT-062-WiFi-BT Pioneer Kit.

       

      Thanks for any assistance - I'm loving the PSOC world, it's just a whole 'nuther level beyond the simpler uC's I've used in the past! :-)

       

      Jim

        • 1. Re: Base Counter component (Verilog) example?
          EktaN_26

          Hello Jim,

           

          You can go through the following appnote:  Designing PSoC Creator™ Components With UDB Datapaths

           

          The appnote mentions the detailed steps on creating an up/down counter using verilog. You can have a look at the project#- Up/Down Counter that comes with the project. You can edit the verilog code to customize the component as per your requirement.

           

          The Application note is for PSoC 3, 4 and 5LP but the same steps can be followed for PSoC 6 as well when using PSoC Creator.

           

          The appnote will also help you to understand the other ways that can also be used for creating a custom component.

           

          Best Regards

          Ekta

          • 2. Re: Base Counter component (Verilog) example?
            BoTa_264741

            JiSt,

            Before diving into Verilog,  I would check if the Counter component already has the count/direction or count_up/count_dn features like PSoC5 UDB Counter has.

            If not, I would try to copy/modify PSoC5 Counter component into your project, which might be not simple, as the component is quite complex.

            The issue with basic counter is that reading the counter require status register, and stock component is only 8-bit wide. Going above  8-bit will require tinkering.

            /odissey1

            • 3. Re: Base Counter component (Verilog) example?
              MoTa_728816

              Hi,

               

              Although I think that using Datapath should be more efficient, I tried using Verilog.

              I used CY8CKIT-062-WiFi-BT.

               

              ========================

              //`#start body` -- edit after this line, do not edit this line

               

              module ud_cntr(

                  input            rst,    /* cync clear */

                  input            clk,    /* clock */

                  input            up_ndn, /* 0: down 1: up */

                  input      [7:0] max,    /* max value */

                  output reg [7:0] cnt,    /* count value */

                  output           tc      /* terminal count */

                  ) ;

                

                  assign tc = (up_ndn == 1'b1) ? cnt == max : cnt == 8'd0 ;

                

                  always @(posedge clk) begin

                      if (rst == 1'b1)

                          if (up_ndn == 1'b1) /* up count */

                              cnt <= 8'd0 ;

                          else /* down count */

                              cnt <= max ;

                      else

                          if (up_ndn == 1'b1) /* up count */

                              if (cnt < max)

                                  cnt <= cnt + 8'd1 ;

                              else

                                cnt <= 8'd0 ;

                          else /* down count */

                             if (cnt > 8'd0)

                                 cnt <= cnt - 8'd1 ;

                             else

                                 cnt <= max ;

                  end

                

              endmodule

               

              //`#end` -- edit above this line, do not edit this line

              ========================

               

              To test the module, I utilized tty_utils.[ch] and func_list.[ch] from my sample code

              MCU Tester, a Swiss Army Knife for PSoC (CY8CKIT-062-BLE version)

               

              Tera Term log

              001-TeraTerm-log.JPG

               

              Schematic

              002-schematic.JPG

              Pins

              003-pins.JPG

              main_cm4.c

              ==================

              #include "project.h"

              #include "stdio.h"

              #include "tty_utils.h"

              #include "func_list.h"

               

              int current_core = USE_CM4 ;

               

              void do_help(void) ;

              void do_step(void) ;

              void do_run(void) ;

              void do_up(void) ;

              void do_down(void) ;

              void do_max(void) ;

              void do_reset(void) ;

              void do_status(void) ;

               

              void cycle_clock(void) ;

              void show_values(void) ;

               

              f_list_type main_func_list[] = {

                  { "help",   do_help,   "show help message"           },

                  { "step",   do_step,   "advance 1 cycle"             },

                  { "run",    do_run,    "advance n cycles:<ex> run 4" },

                  { "up"  ,   do_up,     "set direction to up count"   },

                  { "down",   do_down,   "set direction to down count" },

                  { "max",    do_max,    "set max vaule"               },

                  { "reset",  do_reset,  "reset the counter"           },

                  { "status", do_status, "show current setup"          },

                  { 0,       0,          0 }

              } ;

               

              void init_hardware(void)

              {

                  __enable_irq(); /* Enable global interrupts. */

                 

                  tty_init(USE_CM4) ;

              }

               

              int main(void)

              {

                  func_ptr func ;

                 

                  init_hardware() ;

                

                  cls() ;

                  splash("PSoC 6 Verilog Counter Test") ;

                  do_help() ;

                  prompt("> ") ;

               

                  for(;;)

                  {

                      if (get_line()) {

                          func = get_func(main_func_list, str) ;

                          if (func) {

                              func() ;

                          } else {

                              print("Unknown Command: ") ;

                              print(str) ;

                              print("\r\n") ;

                              do_help() ;

                          }  

                          prompt("> ") ;

                      }   

                  }

              }

               

              void cycle_clock(void)

              {

                  uint8_t tmp ;

                  tmp = Control_Reg_Read() ;

                  tmp = tmp ^ 0x02 ; /* clock = 0 */

                  Control_Reg_Write(tmp) ;

                  tmp = tmp | 0x02 ; /* clock = 1 */

                  Control_Reg_Write(tmp) ;

                  tmp = tmp ^ 0x02 ; /* clock = 0 */  

                  Control_Reg_Write(tmp) ;   

              }

               

              void show_values(void)

              {

                  char buf[32] ;

                  snprintf(buf, 30, "%d %d\n\r", CNT_Read(), TC_Read()) ;

                  print(buf) ;

              }

               

              void do_help(void)

              {

                  show_help(main_func_list) ;

              }

               

              void do_step(void)

              {

                  cycle_clock() ;

                  show_values() ;

              }

               

              void do_run(void)

              {

                  int i, n ;

                  sscanf(str, "%*s %d", &n) ;

                  for (i = 0 ; i < n ; i++ ) {

                      cycle_clock() ;

                      show_values() ;

                      CyDelay(10) ;

                  }

              }

               

              void do_up(void)

              {

                  uint8_t tmp ;

                  tmp = Control_Reg_Read() ;

                  tmp |= 0x4 ; /* up_ndn = 1 */

                  Control_Reg_Write(tmp) ;

              }

               

              void do_down(void)

              {

                  uint8_t tmp ;

                  tmp = Control_Reg_Read() ;

                  tmp ^= 0x4 ; /* up_ndn = 0 */

                  Control_Reg_Write(tmp) ;

              }

               

              void do_max(void)

              {

                  int max ;

                  sscanf(str, "%*s %d", &max) ;

                  max_Write(max) ;

              }

               

              void do_reset(void)

              {

                  uint8_t tmp ;

                  tmp = Control_Reg_Read() ;

                  tmp |= 0x01 ; /* reset = 1 */

                  Control_Reg_Write(tmp) ;

                  cycle_clock() ;

                  tmp ^= 0x01 ; /* reset = 0 */

                  Control_Reg_Write(tmp) ;

                 

                  show_values() ;

              }

               

              void do_status(void)

              {

                  uint8_t tmp, max, cnt, tc ;

                  tmp = Control_Reg_Read() ;

                  max = max_Read() ;

                  cnt = CNT_Read() ;

                  tc = TC_Read() ;

                  print("=== Current Status ===\n\r") ;

                  snprintf(str, STR_BUF_LEN, "Reset: %d\n\r", tmp & 0x01) ;

                  print(str) ;

                  snprintf(str, STR_BUF_LEN, "Clock: %d\n\r", (tmp >> 1) & 0x01) ;

                  print(str) ;

                  print("Direction: ") ;

                  if (tmp & 0x04) {

                      print("Up\n\r") ;

                  } else {

                      print("Down\n\r") ;

                  }

                  snprintf(str, STR_BUF_LEN, "Max: %d\n\r", max) ;

                  print(str) ;

                  snprintf(str, STR_BUF_LEN, "Count: %d\n\r", cnt) ;

                  print(str) ;

                  snprintf(str, STR_BUF_LEN, "Terminal Count: %d\n\r", tc) ;

                  print(str) ;

                  print("\n\r") ; 

              }

              ==================

               

              moto