This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Greetings,
In our CLB implementation, a counter, C0, is used to generate pulses via the zero, match1, and match2 outputs. At the beginning of the transaction there is a rising edge at the EVENT input which causes the counter to load the LOAD VALUE into C0. Later in the transaction, the HLC is used to load R2 into C0. This is the only instruction for the HLC event, and no other HLC events are being used.
The first transaction works perfectly. But when the second transaction begins and the EVENT signal is generated, instead of the LOAD VALUE appearing in the counter, the R2 value is loaded instead. I can find nothing in the TRM which suggests that this will happen. Is this the expected behavior, or did I overlook something in the literature?
In debugging this, I also noted that a write to the LOAD VALUE register also results in the value being written to C0, without needing an event. Is this expected too?
Thank you,
Ed
Ed,
So to summarize:
1. COUNTER mode = LOAD
2. COUNTER EVENT signal is connected to?
Updating the LOAD_val should not automatically update the COUNTER C0 register. only on an EVENT or an HLC triggered instruction should the C0 be updated. What is the EVENT signal?
Nima,
1. Yes
2. The CLB_GP_REG. So the 28x controls the event input of the counter.
I expected this answer, so I created a small project, which uses none of our IP, but demonstrates the issue. I could zip it up and send it to you if you like. If so, please tell me how to attach it.
Thanks,
Ed
Yes just send me your C file and your syscfg file. I will import them into an example project on my side!
Is your EVENT signal high when you write to the COUNTE Cx?
The project has several files including the syscfg file. I have zipped them up, but I can't find a way to attach the file. It seems to want an image or video file.
In the attached project, the EVENT signal is toggled high and low. In our IP, the signal will go high for a prolonged period of time and then go low. But in neither case is LOAD_VAL written during the EVENT signal’s high time. Does a high value on EVENT cause a different behavior when LOAD_VAL is written?
Thank you,
Ed
OK. I’ve combined the files into a single C file which includes the clb_config.h output from the build of the syscfg file, and copied it and the syscfg files below. Hope you can see these. If you put the C0_x variables in order in the Expressions window, you can see the evolution of the C0 value under the various stimuli.
Ed
/////////////////////////////////////////////////////////// // // HLC Overwrites Event Load Value // /////////////////////////////////////////////////////////// #include "clb_config.h" ///////////////////////////////////////// // Data types for this experiment. typedef unsigned int uint16; typedef int int16; typedef unsigned long uint32; typedef long int32; ///////////////////////////////////////// ///////////////////////////////////////// // Access control #define EALLOW __asm(" EALLOW") #define EDIS __asm(" EDIS") ///////////////////////////////////////// ///////////////////////////////////////// // Clock Setup // // Prototypes for the Clock Setup void Setup_Clocks(); // ///////////////////////////////////////// ///////////////////////////////////////// // CLB Access // Board input values #define BOUNDARY_INPUT_0 0x01 #define BOUNDARY_INPUT_1 0x02 #define BOUNDARY_INPUT_2 0x04 #define BOUNDARY_INPUT_3 0x08 #define BOUNDARY_INPUT_4 0x10 #define BOUNDARY_INPUT_5 0x20 #define BOUNDARY_INPUT_6 0x40 #define BOUNDARY_INPUT_7 0x80 // Translate the generic boundary inputs into their respective signals. #define COUNTER0_RESET BOUNDARY_INPUT_0 #define COUNTER0_EVENT BOUNDARY_INPUT_1 #define HLC_EV0_EVENT BOUNDARY_INPUT_2 // Logic Config Registers #define CLB4_LOGIC_CFG_REGS 0x3C00 #define CLB_COUNT_RESET 0x02 #define CLB_COUNT_MODE_1 0x04 #define CLB_COUNT_MODE_0 0x06 #define CLB_COUNT_EVENT 0x08 #define CLB_MISC_CONTROL 0x2A #define CLB_HLC_EVENT_SEL 0x3C // Logic Control Registers #define CLB4_LOGIC_CTL_REGS 0x3D00 #define CLB_LOAD_EN 0x00 #define CLB_LOAD_ADDR 0x02 #define CLB_LOAD_DATA 0x04 #define CLB_IN_MUX_SEL_0 0x08 #define CLB_GP_REG 0x10 #define CLB_DBG_C0 0x38 // CLB_LOAD_EN data fields #define LOAD_EN 1 #define GLOBAL_EN 2 // Register values for CLB_IN_MUX_SEL_0 #define SEL_GP_IN_0 0x01 #define SEL_GP_IN_1 0x02 #define SEL_GP_IN_2 0x04 #define SEL_GP_IN_3 0x08 #define SEL_GP_IN_4 0x10 #define SEL_GP_IN_5 0x20 #define SEL_GP_IN_6 0x40 #define SEL_GP_IN_7 0x80 // Indirect Registers #define COUNTER0_LOAD_VAL_ADDR 0x0000 #define COUNTER1_LOAD_VAL_ADDR 0x0001 #define COUNTER2_LOAD_VAL_ADDR 0x0002 #define COUNTER0_MATCH1_ADDR 0x0004 #define COUNTER1_MATCH1_ADDR 0x0005 #define COUNTER2_MATCH1_ADDR 0x0006 #define COUNTER0_MATCH2_ADDR 0x0008 #define COUNTER1_MATCH2_ADDR 0x0009 #define COUNTER2_MATCH2_ADDR 0x000A #define R0_ADDR 0x000C #define R1_ADDR 0x000D #define R2_ADDR 0x000E #define R3_ADDR 0x000F #define INSTRUCTIONS_EVENT0_ADDR 0x0020 // Instructions for all the HLCs. #define HLC_INSTRUCTIONS_PER_TILE 32 uint32 HlcInstructions[HLC_INSTRUCTIONS_PER_TILE] = { Tile4_HLCINSTR_0, Tile4_HLCINSTR_1, Tile4_HLCINSTR_2, Tile4_HLCINSTR_3, Tile4_HLCINSTR_4, Tile4_HLCINSTR_5, Tile4_HLCINSTR_6, Tile4_HLCINSTR_7, Tile4_HLCINSTR_8, Tile4_HLCINSTR_9, Tile4_HLCINSTR_10, Tile4_HLCINSTR_11, Tile4_HLCINSTR_12, Tile4_HLCINSTR_13, Tile4_HLCINSTR_14, Tile4_HLCINSTR_15, Tile4_HLCINSTR_16, Tile4_HLCINSTR_17, Tile4_HLCINSTR_18, Tile4_HLCINSTR_19, Tile4_HLCINSTR_20, Tile4_HLCINSTR_21, Tile4_HLCINSTR_22, Tile4_HLCINSTR_23, Tile4_HLCINSTR_24, Tile4_HLCINSTR_25, Tile4_HLCINSTR_26, Tile4_HLCINSTR_27, Tile4_HLCINSTR_28, Tile4_HLCINSTR_29, Tile4_HLCINSTR_30, Tile4_HLCINSTR_31 }; // Prototypes Public void Setup_CLB(); void Toggle_Input(uint16 boundary_input); uint32 Get_C0(); // Prototypes Private void Write_IndirectRegister(uint32 address, uint32 data); void Setup_Counters(); void Setup_HLC(); void Disable_CLB(); void Enable_CLB(); // ///////////////////////////////////////// // Variables to capture the state of C0 at various points in the process. uint32 C0_0_BeforeFirstCounterReset = 0; uint32 C0_1_AfterFirstCounterReset = 0; uint32 C0_2_BeforeFirstCounterEvent = 0; uint32 C0_3_AfterFirstCounterEvent = 0; uint32 C0_4_BeforeHlcEvent = 0; uint32 C0_5_AfterHlcEvent = 0; uint32 C0_6_BeforeSecondCounterReset = 0; uint32 C0_7_AfterSecondCounterReset = 0; uint32 C0_8_BeforeSecondCounterEvent = 0; uint32 C0_9_AfterSecondCounterEvent = 0; //////////////////////////////////////////////////////////////////////////////////////////////////// // // The test consists of the following steps each of which is preceded and followed by a capture // of the state of the counter register (C0). // // Action Result Conclusion // --------------------------------------------------------------------------- // Counter Reset - Clears C0 - Pass // Counter Event - Puts the LOAD VALUE into C0 - Pass // HLC Event - Loads R2 into C0 - Pass // Counter Reset - Clears C0 - Pass // Counter Event - Puts the R2 value into C0, not the LOAD VALUE - FAIL // //////////////////////////////////////////////////////////////////////////////////////////////////// void main(void) { // Setup the clocks Setup_Clocks(); // Setup the CLB Setup_CLB(); ///////////////////////////////////////////////////////////////////////////////////////////////// // Record the value of the counter before and after the first reset ///////////////////////////////////////////////////////////////////////////////////////////////// C0_0_BeforeFirstCounterReset = Get_C0(); // Record the counter before the reset Toggle_Input(COUNTER0_RESET); // Toggle the reset event C0_1_AfterFirstCounterReset = Get_C0(); // Record the counter value after the reset ///////////////////////////////////////////////////////////////////////////////////////////////// // Record the value of the counter before and after the first counter event ///////////////////////////////////////////////////////////////////////////////////////////////// C0_2_BeforeFirstCounterEvent = Get_C0(); // Record the counter before the event Toggle_Input(COUNTER0_EVENT); // Toggle the counter event C0_3_AfterFirstCounterEvent = Get_C0(); // Record the counter value after the event ///////////////////////////////////////////////////////////////////////////////////////////////// // Record the value of the counter before and after the HLC event ///////////////////////////////////////////////////////////////////////////////////////////////// C0_4_BeforeHlcEvent = Get_C0(); // Record the counter value before the event Toggle_Input(HLC_EV0_EVENT); // Toggle the HLC event C0_5_AfterHlcEvent = Get_C0(); // Record the counter value after the event ///////////////////////////////////////////////////////////////////////////////////////////////// // Record the value of the counter before and after the second reset ///////////////////////////////////////////////////////////////////////////////////////////////// C0_6_BeforeSecondCounterReset = Get_C0(); // Record the counter before the reset Toggle_Input(COUNTER0_RESET); // Toggle the reset event C0_7_AfterSecondCounterReset = Get_C0(); // Record the counter value after the reset ///////////////////////////////////////////////////////////////////////////////////////////////// // Record the value of the counter before and after the second counter event // // THIS IS WERE THE FAILURE IS SEEN. C0_9_AfterSecondCounterEvent will contain the incorrect // value. ///////////////////////////////////////////////////////////////////////////////////////////////// C0_8_BeforeSecondCounterEvent = Get_C0(); // Record the counter value before the event Toggle_Input(COUNTER0_EVENT); // Toggle the counter event C0_9_AfterSecondCounterEvent = Get_C0(); // Record the counter value after the event // Hang so we can look at the results. while(1); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Start Clock Setup Code // // Clock config registers #define CLK_CFG_REGS 0x05D200 #define CLKSRCCTL1 0x08 #define SYSPLLCTL1 0x0E #define SYSPLLMULT 0x14 #define SYSPLLSTS 0x16 #define SYSCLKDIVSEL 0x22 // CPU Sys Registers #define CPU_SYS_REGS 0x05D300 #define PCLKCR2 0x26 // PCLKR2 Register #define ALL_EPWMS 0x0FFF // CLKSRCCTL1 Register Values #define XTALOFF 0x10 #define OSCCLKSRCSEL_INIT 1 // AUXPLLCTL1 Register #define PLLCLKEN 2 void Setup_Clocks() { EALLOW; uint32 clk_src_ctl1 = *(uint32*)(CLK_CFG_REGS + CLKSRCCTL1); clk_src_ctl1 |= OSCCLKSRCSEL_INIT; clk_src_ctl1 &= ~XTALOFF; *(uint32*)(CLK_CFG_REGS + CLKSRCCTL1) = clk_src_ctl1; *(uint32*)(CLK_CFG_REGS + SYSPLLCTL1) &= ~2; *(uint32*)(CLK_CFG_REGS + SYSCLKDIVSEL) = 0; *(uint32*)(CLK_CFG_REGS + SYSPLLMULT) = 10; *(uint32*)(CLK_CFG_REGS + SYSPLLCTL1) |= 1; // Wait for the PLL to lock while(1 != (*(uint32*)(CLK_CFG_REGS + SYSPLLSTS) & 1)) { } *(uint32*)(CLK_CFG_REGS + SYSPLLCTL1) |= PLLCLKEN; asm(" RPT #100 || NOP"); *(uint32*)(CLK_CFG_REGS + SYSCLKDIVSEL) = 0; // Enable the clocks which supply the CLB *(uint32*)(CPU_SYS_REGS + PCLKCR2) = ALL_EPWMS; EDIS; } // // End Clock Setup Code // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Start CLB Code // /////////////////////////////////////////////////////////// // // Setup_CLB // /////////////////////////////////////////////////////////// void Setup_CLB() { // Setup so we can load the CLB. Disable_CLB(); // Set an initial value for the cell inputs. *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_GP_REG) = 0; // Setup Boundary Inputs 0, 1 and 2 to be controlled by // the processor. EALLOW; *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_IN_MUX_SEL_0) |= SEL_GP_IN_0; *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_IN_MUX_SEL_0) |= SEL_GP_IN_1; *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_IN_MUX_SEL_0) |= SEL_GP_IN_2; EDIS; // Setup the tile's Counters Setup_Counters(); // Setup the HLC Setup_HLC(); // Enable the CLB. Enable_CLB(); } /////////////////////////////////////////////////////////// // // Toggle_Input // /////////////////////////////////////////////////////////// void Toggle_Input(uint16 boundary_input) { // Toggle the requested input *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_GP_REG) |= boundary_input; *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_GP_REG) &= ~boundary_input; } /////////////////////////////////////////////////////////// // // Get_C0 // /////////////////////////////////////////////////////////// uint32 Get_C0() { // Return the current value of the debug register. return *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_DBG_C0); } /////////////////////////////////////////////////////////// // // Write_IndirectRegister // /////////////////////////////////////////////////////////// void Write_IndirectRegister(uint32 address, uint32 data) { // Setup the address and data *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_LOAD_ADDR) = address; *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_LOAD_DATA) = data; // Write the value. EALLOW; *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_LOAD_EN) |= LOAD_EN; EDIS; } /////////////////////////////////////////////////////////// // // Setup_Counter // /////////////////////////////////////////////////////////// void Setup_Counters() { // Load the logic config registers. EALLOW; *(uint32*)(CLB4_LOGIC_CFG_REGS + CLB_COUNT_RESET) = Tile4_CFG_COUNTER_RESET; *(uint32*)(CLB4_LOGIC_CFG_REGS + CLB_COUNT_MODE_1) = Tile4_CFG_COUNTER_MODE_1; *(uint32*)(CLB4_LOGIC_CFG_REGS + CLB_COUNT_MODE_0) = Tile4_CFG_COUNTER_MODE_0; *(uint32*)(CLB4_LOGIC_CFG_REGS + CLB_COUNT_EVENT) = Tile4_CFG_COUNTER_EVENT; *(uint32*)(CLB4_LOGIC_CFG_REGS + CLB_MISC_CONTROL) = Tile4_CFG_MISC_CONTROL; EDIS; // Load the event load registers. Write_IndirectRegister(COUNTER0_LOAD_VAL_ADDR, Tile4_COUNTER_0_LOAD_VAL); Write_IndirectRegister(COUNTER1_LOAD_VAL_ADDR, Tile4_COUNTER_1_LOAD_VAL); Write_IndirectRegister(COUNTER2_LOAD_VAL_ADDR, Tile4_COUNTER_2_LOAD_VAL); // Load the match1 registers. Write_IndirectRegister(COUNTER0_MATCH1_ADDR, Tile4_COUNTER_0_MATCH1_VAL); Write_IndirectRegister(COUNTER1_MATCH1_ADDR, Tile4_COUNTER_1_MATCH1_VAL); Write_IndirectRegister(COUNTER2_MATCH1_ADDR, Tile4_COUNTER_2_MATCH1_VAL); // Load the match2 registers. Write_IndirectRegister(COUNTER0_MATCH2_ADDR, Tile4_COUNTER_0_MATCH2_VAL); Write_IndirectRegister(COUNTER1_MATCH2_ADDR, Tile4_COUNTER_1_MATCH2_VAL); Write_IndirectRegister(COUNTER2_MATCH2_ADDR, Tile4_COUNTER_2_MATCH2_VAL); } /////////////////////////////////////////////////////////// // // Setup_HLC // /////////////////////////////////////////////////////////// void Setup_HLC() { // Load the event instructions uint32 address = INSTRUCTIONS_EVENT0_ADDR; for(uint32 j = 0 ; j < HLC_INSTRUCTIONS_PER_TILE; j++, address++) { Write_IndirectRegister(address, HlcInstructions[j]); } // Configure the events EALLOW; *(uint32*)(CLB4_LOGIC_CFG_REGS + CLB_HLC_EVENT_SEL) = Tile4_HLC_EVENT_SEL; EDIS; // Load the HLC's registers Write_IndirectRegister(R0_ADDR, Tile4_HLC_R0_INIT); Write_IndirectRegister(R1_ADDR, Tile4_HLC_R1_INIT); Write_IndirectRegister(R2_ADDR, Tile4_HLC_R2_INIT); Write_IndirectRegister(R3_ADDR, Tile4_HLC_R3_INIT); } /////////////////////////////////////////////////////////// // // Disable_CLB // /////////////////////////////////////////////////////////// void Disable_CLB() { EALLOW; *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_LOAD_EN) &= ~GLOBAL_EN; EDIS; } /////////////////////////////////////////////////////////// // // Enable_CLB // /////////////////////////////////////////////////////////// void Enable_CLB() { EALLOW; *(uint32*)(CLB4_LOGIC_CTL_REGS + CLB_LOAD_EN) |= GLOBAL_EN; EDIS; } // // End CLB Code // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// These arguments were used when this file was generated. They will be automatically applied on subsequent loads // via the GUI or CLI invocations. Run CLI with '--help' for additional information on how to override these arguments. // @cliArgs --device "CC3200" --package "Default" --part "Default" --product "CLB Configuration Tool@1.0.0" // @versions {"data":"2019051709","timestamp":"2019051709","tool":"1.1.792","templates":"2019051709"} var TILE = scripting.addModule("/utilities/clb_tool/clb_syscfg/source/TILE"); var TILE1 = TILE.addInstance(); var TILE2 = TILE.addInstance(); var TILE3 = TILE.addInstance(); var TILE4 = TILE.addInstance(); // clock_period - Period of the clock (in Nano Seconds) used for simulation in System C TILE.clock_period = 5; // reset_duration - Time at which reset signal is deassrted, specified in Nano Seconds TILE.reset_duration = 1; // sim_duration - Duration of the simulation (in Nano Seconds) TILE.sim_duration = 2000; // Name TILE1.$name = "Tile1"; // Name TILE1.BOUNDARY.$name = "BOUNDARY0"; // in0 TILE1.BOUNDARY.in0 = "squareWave"; // in_duty0 - Duty or ON time of the square wave TILE1.BOUNDARY.in_duty0 = 1; // in_repeat_count0 - Number of periods the waveform is repeated TILE1.BOUNDARY.in_repeat_count0 = 1; // in1 TILE1.BOUNDARY.in1 = "TILE2_BOUNDARY.out5"; // in_period0 - Period of the square wave TILE1.BOUNDARY.in_period0 = 2; // Name TILE1.LUT_0.$name = "LUT_0"; // Name TILE1.LUT_1.$name = "LUT_1"; // Name TILE1.LUT_2.$name = "LUT_2"; // Name TILE1.FSM_0.$name = "FSM_0"; // Name TILE1.FSM_1.$name = "FSM_1"; // eqn_s1 - Boolean equation on the variables e1,e0,s1,s0 for the S1 output. TILE1.FSM_1.eqn_s1 = "0"; // Name TILE1.FSM_2.$name = "FSM_2"; // Name TILE1.COUNTER_0.$name = "COUNTER_0"; // Name TILE1.COUNTER_1.$name = "COUNTER_1"; // Name TILE1.COUNTER_2.$name = "COUNTER_2"; // Name TILE1.OUTLUT_0.$name = "OUTLUT_0"; // Name TILE1.OUTLUT_1.$name = "OUTLUT_1"; // Name TILE1.OUTLUT_2.$name = "OUTLUT_2"; // Name TILE1.OUTLUT_3.$name = "OUTLUT_3"; // Name TILE1.OUTLUT_4.$name = "OUTLUT_4"; // Name TILE1.OUTLUT_5.$name = "OUTLUT_5"; // Name TILE1.OUTLUT_6.$name = "OUTLUT_6"; // Name TILE1.OUTLUT_7.$name = "OUTLUT_7"; // Name TILE1.HLC.$name = "HLC_0"; // Name TILE1.HLC.program0.$name = "HLCP_0"; // Name TILE1.HLC.program1.$name = "HLCP_1"; // Name TILE1.HLC.program2.$name = "HLCP_2"; // Name TILE1.HLC.program3.$name = "HLCP_3"; var clb_run_dynamic_template_clb_h = scripting.addModule("/utilities/clb_tool/clb_syscfg/source/clb_run_dynamic_template_clb_h.js"); var clb_run_dynamic_template_clb_c = scripting.addModule("/utilities/clb_tool/clb_syscfg/source/clb_run_dynamic_template_clb_c.js"); var clb_run_dynamic_template_clb_sim = scripting.addModule("/utilities/clb_tool/clb_syscfg/source/clb_run_dynamic_template_clb_sim.js"); var clb_run_dynamic_template_clb_dot = scripting.addModule("/utilities/clb_tool/clb_syscfg/source/clb_run_dynamic_template_clb_dot.js"); // Name TILE2.$name = "Tile2"; // Name TILE2.BOUNDARY.$name = "BOUNDARY2"; // in0 TILE2.BOUNDARY.in0 = "squareWave"; // in_period0 - Period of the square wave TILE2.BOUNDARY.in_period0 = 40; // in_duty0 - Duty or ON time of the square wave TILE2.BOUNDARY.in_duty0 = 20; // in_repeat_count0 - Number of periods the waveform is repeated TILE2.BOUNDARY.in_repeat_count0 = 4; // Name TILE2.LUT_0.$name = "LUT_6"; // Name TILE2.LUT_1.$name = "LUT_7"; // Name TILE2.LUT_2.$name = "LUT_8"; // Name TILE2.FSM_0.$name = "FSM_6"; // Name TILE2.FSM_1.$name = "FSM_7"; // Name TILE2.FSM_2.$name = "FSM_8"; // Name TILE2.COUNTER_0.$name = "COUNTER_6"; // Name TILE2.COUNTER_1.$name = "COUNTER_7"; // Name TILE2.COUNTER_2.$name = "COUNTER_8"; // Name TILE2.OUTLUT_0.$name = "OUTLUT_16"; // Name TILE2.OUTLUT_1.$name = "OUTLUT_17"; // Name TILE2.OUTLUT_2.$name = "OUTLUT_18"; // Name TILE2.OUTLUT_3.$name = "OUTLUT_19"; // Name TILE2.OUTLUT_4.$name = "OUTLUT_20"; // Name TILE2.OUTLUT_5.$name = "OUTLUT_21"; // Name TILE2.OUTLUT_6.$name = "OUTLUT_22"; // Name TILE2.OUTLUT_7.$name = "OUTLUT_23"; // Name TILE2.HLC.$name = "HLC_2"; // Name TILE2.HLC.program0.$name = "HLCP_8"; // Name TILE2.HLC.program1.$name = "HLCP_9"; // Name TILE2.HLC.program2.$name = "HLCP_10"; // Name TILE2.HLC.program3.$name = "HLCP_11"; // Name TILE3.$name = "Tile3"; // Name TILE3.BOUNDARY.$name = "BOUNDARY1"; // Name TILE3.LUT_0.$name = "LUT_3"; // Name TILE3.LUT_1.$name = "LUT_4"; // Name TILE3.LUT_2.$name = "LUT_5"; // Name TILE3.FSM_0.$name = "FSM_3"; // Name TILE3.FSM_1.$name = "FSM_4"; // Name TILE3.FSM_2.$name = "FSM_5"; // Name TILE3.COUNTER_0.$name = "COUNTER_3"; // Name TILE3.COUNTER_1.$name = "COUNTER_4"; // Name TILE3.COUNTER_2.$name = "COUNTER_5"; // Name TILE3.OUTLUT_0.$name = "OUTLUT_8"; // Name TILE3.OUTLUT_1.$name = "OUTLUT_9"; // Name TILE3.OUTLUT_2.$name = "OUTLUT_10"; // Name TILE3.OUTLUT_3.$name = "OUTLUT_11"; // Name TILE3.OUTLUT_4.$name = "OUTLUT_12"; // Name TILE3.OUTLUT_5.$name = "OUTLUT_13"; // Name TILE3.OUTLUT_6.$name = "OUTLUT_14"; // Name TILE3.OUTLUT_7.$name = "OUTLUT_15"; // Name TILE3.HLC.$name = "HLC_1"; // Name TILE3.HLC.program0.$name = "HLCP_4"; // Name TILE3.HLC.program1.$name = "HLCP_5"; // Name TILE3.HLC.program2.$name = "HLCP_6"; // Name TILE3.HLC.program3.$name = "HLCP_7"; // Name TILE4.$name = "Tile4"; // Name TILE4.BOUNDARY.$name = "BOUNDARY3"; // Name TILE4.LUT_0.$name = "LUT_9"; // Name TILE4.LUT_1.$name = "LUT_10"; // Name TILE4.LUT_2.$name = "LUT_11"; // Name TILE4.FSM_0.$name = "FSM_9"; // Name TILE4.FSM_1.$name = "FSM_10"; // Name TILE4.FSM_2.$name = "FSM_11"; // Name TILE4.COUNTER_0.$name = "COUNTER_9"; // What action should be taken on an event trigger? TILE4.COUNTER_0.action = "Load"; // event - Trigger actions in the counter. TILE4.COUNTER_0.event = "BOUNDARY.in1"; // reset - Reset the counter to 0 on next clock cycle (triggers low to high) TILE4.COUNTER_0.reset = "BOUNDARY.in0"; // event_load_val - Sets the value of the event load value register. TILE4.COUNTER_0.event_load_val = "0xAAAAAAAA"; // Name TILE4.COUNTER_1.$name = "COUNTER_10"; // Name TILE4.COUNTER_2.$name = "COUNTER_11"; // Name TILE4.OUTLUT_0.$name = "OUTLUT_24"; // Name TILE4.OUTLUT_1.$name = "OUTLUT_25"; // Name TILE4.OUTLUT_2.$name = "OUTLUT_26"; // Name TILE4.OUTLUT_3.$name = "OUTLUT_27"; // Name TILE4.OUTLUT_4.$name = "OUTLUT_28"; // Name TILE4.OUTLUT_5.$name = "OUTLUT_29"; // Name TILE4.OUTLUT_6.$name = "OUTLUT_30"; // Name TILE4.OUTLUT_7.$name = "OUTLUT_31"; // Name TILE4.HLC.$name = "HLC_3"; // Event 0 (e0) - Event 0 TILE4.HLC.e0 = "BOUNDARY.in2"; // R2_init - Initial value for register R2 TILE4.HLC.R2_init = "0x55555555"; // Name TILE4.HLC.program0.$name = "HLCP_12"; // instruct0 TILE4.HLC.program0.instruct0 = "MOV R2, C0"; // Name TILE4.HLC.program1.$name = "HLCP_13"; // Name TILE4.HLC.program2.$name = "HLCP_14"; // Name TILE4.HLC.program3.$name = "HLCP_15";
Ed,
I just ran the following scenario, and you are correct. When the CLB counter is in Load mode, and the load value is change:
CLB_configCounterLoadMatch(CLB1_BASE, CLB_CTR0, 5000, 8000, 0);
Whether the CLB is enabled or disabled, the C0 (counter's active counter value) is also updated to the LOAD value. WITHOUT AN EVENT signal.
This is certainly something that we will document in the TRM.
Nima
For your reference:
#include "driverlib.h" #include "device.h" #include "clb_config.h" #include "clb.h" __interrupt void clb1ISR(void); #define EVENT_TIMER 1 #define ENABLE_TIMER 2 #define COUNTUP_MODE 4 void main(void) { Device_init(); Device_initGPIO(); Interrupt_initModule(); Interrupt_initVectorTable(); // // Enabling EPWM1 to enable CLB1 // SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1); CLB_disableCLB(CLB1_BASE); initTILE1(CLB1_BASE); // // Select Global input instead of local input for all CLB IN // CLB_configLocalInputMux(CLB1_BASE, CLB_IN0, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN1, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN2, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN3, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN4, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN5, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN6, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN7, CLB_LOCAL_IN_MUX_GLOBAL_IN); // // Unused Inputs below // CLB_configGlobalInputMux(CLB1_BASE, CLB_IN0, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN1, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN2, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN3, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN4, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN5, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN6, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN7, CLB_GLOBAL_IN_MUX_EPWM1A); // // Inputs set to GP register // CLB_configGPInputMux(CLB1_BASE, CLB_IN0, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN1, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN2, CLB_GP_IN_MUX_GP_REG); // // Unused inputs to GP register // CLB_configGPInputMux(CLB1_BASE, CLB_IN3, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN4, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN5, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN6, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN7, CLB_GP_IN_MUX_GP_REG); CLB_enableCLB(CLB1_BASE); CLB_setGPREG(CLB1_BASE, ENABLE_TIMER | COUNTUP_MODE); // // Enable Global Interrupt (INTM) and realtime interrupt (DBGM) // EINT; ERTM; uint32_t c0 = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); uint32_t c0_later = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); CLB_configCounterLoadMatch(CLB1_BASE, CLB_CTR0, 5000, 8000, 0); //CLB_setGPREG(CLB1_BASE, ENABLE_TIMER | COUNTUP_MODE | EVENT_TIMER); uint32_t c0_after_event = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); uint32_t c0_after_event_later = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); ESTOP0; while(1) { } }
In the code, you can see that if you run this, it will halt on ESTOP0.
The values are:
I will add this to the TRM as a note.
Ahh. You took my experiment a step further. Great information. Thank you!
In my experiment, I also used the HLC to load C0, and the appearance is that the LOAD_VALUE register was written too because, after the HLC event, when the counter event occurs, C0 is written with the value from the HLC, not the original value written to the LOAD_VALUE register. Is it possible that the HLC writes to C0 through the LOAD_VALUE register using the mechanism you illustrated above?
Thank you,
Ed
I dont think HLC can update the LOAD_val. HLC directly updates the C0. We can check this too to confirm!
Thank you for checking. The middle step in my experiment uses the HLC to load C0 with a value, in R2, which is different from the value loaded into LOAD_VALUE. After the HLC event, it shows that C0 contains the value in the HLC's R2 register. After a reset of the counter to put 0 into C0, the counter event is toggled and the R2 value can then be seen in C0, not the original LOAD_VALUE.
Thanks,
Ed
I'm going to code this too really quick and we can add this to the TRM as well.
Nima
Yes the HLC MOVing value from Rx to C0, updates the LOAD_val as well.
Main.c file
#include "driverlib.h" #include "device.h" #include "clb_config.h" #include "clb.h" __interrupt void clb1ISR(void); #define EVENT_TIMER 1 #define ENABLE_TIMER 2 #define COUNTUP_MODE 4 #define HLC_TRIG 8 void main(void) { Device_init(); Device_initGPIO(); Interrupt_initModule(); Interrupt_initVectorTable(); // // Enabling EPWM1 to enable CLB1 // SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1); CLB_disableCLB(CLB1_BASE); initTILE1(CLB1_BASE); // // Select Global input instead of local input for all CLB IN // CLB_configLocalInputMux(CLB1_BASE, CLB_IN0, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN1, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN2, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN3, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN4, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN5, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN6, CLB_LOCAL_IN_MUX_GLOBAL_IN); CLB_configLocalInputMux(CLB1_BASE, CLB_IN7, CLB_LOCAL_IN_MUX_GLOBAL_IN); // // Unused Inputs below // CLB_configGlobalInputMux(CLB1_BASE, CLB_IN0, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN1, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN2, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN3, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN4, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN5, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN6, CLB_GLOBAL_IN_MUX_EPWM1A); CLB_configGlobalInputMux(CLB1_BASE, CLB_IN7, CLB_GLOBAL_IN_MUX_EPWM1A); // // Inputs set to GP register // CLB_configGPInputMux(CLB1_BASE, CLB_IN0, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN1, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN2, CLB_GP_IN_MUX_GP_REG); // // Unused inputs to GP register // CLB_configGPInputMux(CLB1_BASE, CLB_IN3, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN4, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN5, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN6, CLB_GP_IN_MUX_GP_REG); CLB_configGPInputMux(CLB1_BASE, CLB_IN7, CLB_GP_IN_MUX_GP_REG); CLB_enableCLB(CLB1_BASE); CLB_setGPREG(CLB1_BASE, ENABLE_TIMER | COUNTUP_MODE); // // Enable Global Interrupt (INTM) and realtime interrupt (DBGM) // EINT; ERTM; uint32_t c0 = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); uint32_t c0_later = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); CLB_configCounterLoadMatch(CLB1_BASE, CLB_CTR0, 5000, 8000, 0); //CLB_setGPREG(CLB1_BASE, ENABLE_TIMER | COUNTUP_MODE | EVENT_TIMER); uint32_t c0_after_load_changed = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); uint32_t c0_after_load_changed_later = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); #if 0 CLB_disableCLB(CLB1_BASE); uint32_t c0_after_disable = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); uint32_t c0_after_disable_later = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); CLB_enableCLB(CLB1_BASE); uint32_t c0_after_enable = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); uint32_t c0_after_enable_later = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); #endif CLB_setGPREG(CLB1_BASE, ENABLE_TIMER | COUNTUP_MODE | HLC_TRIG); // HLC Loads 6000 to C0 uint32_t c0_after_HLC = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); uint32_t c0_after_HLC_later = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); CLB_setGPREG(CLB1_BASE, ENABLE_TIMER | COUNTUP_MODE | EVENT_TIMER); // Generate an EVENT trigger to see what value is loaded into C0 uint32_t c0_after_EVENT = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); uint32_t c0_after_EVENT_later = CLB_getRegister(CLB1_BASE, CLB_REG_CTR_C0); ESTOP0; while(1) { } }
SysCfg File
/** * These arguments were used when this file was generated. They will be automatically applied on subsequent loads * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments. * @cliArgs --device "F2837xD" --package "F2837xD_176PTP" --part "F2837xD_176PTP" --product "CLB Configuration Tool@4.0.0" * @versions {"tool":"1.10.0+2029"} */ /** * Import the modules used in this configuration. */ const TILE = scripting.addModule("/utilities/clb_tool/clb_syscfg/source/TILE"); const TILE1 = TILE.addInstance(); /** * Write custom configuration values to the imported modules. */ TILE.clock_period = 10; TILE.sim_duration = 100000; TILE1.$name = "TILE1"; TILE1.BOUNDARY.$name = "BOUNDARY0"; TILE1.BOUNDARY.in_repeat_count0 = 50; TILE1.BOUNDARY.in_repeat_count3 = 1; TILE1.BOUNDARY.in0 = "squareWave"; TILE1.BOUNDARY.in_repeat_count1 = 50; TILE1.BOUNDARY.in_repeat_count2 = 50; TILE1.BOUNDARY.in_period0 = 10000; TILE1.BOUNDARY.in_duty0 = 5001; TILE1.BOUNDARY.in_period1 = 1000; TILE1.BOUNDARY.in_duty1 = 500; TILE1.BOUNDARY.in_period2 = 3000; TILE1.BOUNDARY.in_duty2 = 1500; TILE1.BOUNDARY.in1 = "1"; TILE1.BOUNDARY.in2 = "1"; TILE1.LUT_0.$name = "LUT_0"; TILE1.LUT_1.$name = "LUT_1"; TILE1.LUT_2.$name = "LUT_2"; TILE1.FSM_0.$name = "FSM_0"; TILE1.FSM_0.e0 = "COUNTER_0.count_match1"; TILE1.FSM_0.eqn_s0 = "e0 ^ s0"; TILE1.FSM_1.$name = "FSM_1"; TILE1.FSM_2.$name = "FSM_2"; TILE1.COUNTER_0.$name = "COUNTER_0"; TILE1.COUNTER_0.action = "Load"; TILE1.COUNTER_0.reset = "COUNTER_0.count_match1"; TILE1.COUNTER_0.event = "BOUNDARY.in0"; TILE1.COUNTER_0.mode0 = "BOUNDARY.in1"; TILE1.COUNTER_0.mode1 = "BOUNDARY.in2"; TILE1.COUNTER_0.match1_val = "8000"; TILE1.COUNTER_0.event_load_val = "2000"; TILE1.COUNTER_1.$name = "COUNTER_1"; TILE1.COUNTER_2.$name = "COUNTER_2"; TILE1.OUTLUT_0.$name = "OUTLUT_0"; TILE1.OUTLUT_1.$name = "OUTLUT_1"; TILE1.OUTLUT_2.$name = "OUTLUT_2"; TILE1.OUTLUT_3.$name = "OUTLUT_3"; TILE1.OUTLUT_4.$name = "OUTLUT_4"; TILE1.OUTLUT_5.$name = "OUTLUT_5"; TILE1.OUTLUT_6.$name = "OUTLUT_6"; TILE1.OUTLUT_7.$name = "OUTLUT_7"; TILE1.HLC.$name = "HLC_0"; TILE1.HLC.e0 = "BOUNDARY.in3"; TILE1.HLC.R0_init = "6000"; TILE1.HLC.program0.$name = "HLCP_0"; TILE1.HLC.program0.instruct0 = "MOV R0,C0"; TILE1.HLC.program1.$name = "HLCP_1"; TILE1.HLC.program2.$name = "HLCP_2"; TILE1.HLC.program3.$name = "HLCP_3";