On Oct 18, 7:33*am, KJ <kkjenni...@sbcglobal.net> wrote:
> On Oct 17, 4:16*pm, Lango <mr.ara...@gmail.com> wrote:
>
> > Hello. *I normally have the control description (normally a fsm)
> > separate from the datapath.
>
> That's a religious thing, not a design requirement or anything that
> necessarily improves anything...but OK.
>
> > Supposing I need a counter to time the
> > duration of some of the control outputs, for example, enable this mux
> > for 1000 cycles before doing anything else, would you declare the
> > counter inside or outside of the fsm architecture?
>
> Depends on what you mean by 'fsm architecture'. *For the sake of
> discussion, I'll assume that you mean a VHDL 'process'. *Next, I
> wouldn't get philosophical about it but instead focus on the
> readability and maintainability of the design. *A VHDL process that
> requires paging back and forth in order to be understood likely does
> not rank very high on the readability and maintainability score (which
> is subjective). *Given no other information about what function is to
> be accomplished in the entity I would most likely start like the code
> I've shown below.
>
> If either the counter logic or the FSM logic (or other logic in the
> architecture) grew to the point where the process gets to be too long,
> I would likely break it up into separate clocked processes just to try
> to keep related things together and try to make it a bit easier to
> understand.
>
> Long processes can spawn use of numerous variables. *While variables
> are a good thing, assignments to variables create a line in the sand.
> Prior to the assignment, the variable means one thing, after the
> assignment it means something else. *Since code generally tends to
> grow over time and not shrink it can cause problems if the code starts
> to look a bit unwieldy since you can't easily move things around
> without destroying the function. *In my example, I didn't use
> variables so the logic implementing the FSM and the logic implementing
> the counter could be rearranged as separate block for readability
> however I see fit...it's all happening in parallel.
>
> You having the take that control logic must be separated from control
> logic you've put up some artificial barriers that are philosophical
> but do not contribute to making a design more robust or maintainable.
> As I wrote it, the counter is separated from the control logic but not
> because of any philosophy. *The two functions are loosely coupled (the
> FSM tells the counter to start, the counter tells the FSM when it's
> done) so the logic to implement each tends to not want to live inside
> the other.
>
> A more pragmatic approach that will lead to better design is to view
> sub-functions to see if they fit the model of 'request/acknowledge' or
> 'start/complete' 'command/wait' (whichever works for you). *You'll
> find that in many cases they do. *In this case, the FSM commands the
> counter to start (via being in a particular state...or could've been
> as a separate signal if you prefer) and the counter then signals back
> when it completes (via the 'Done_Counting' signal). *Once you take
> that viewpoint, you'll probably see that the logic for sub-functions
> naturally separates into more readable, maintainable code.
>
> Kevin Jennings
> ----
> architecture RTL of Something is
> * type t_STATES is (Idle, Start_Count, Done);
> * signal Current_State: t_STATES;
> * constant MAX_COUNT: natural := 999;
> * signal Counter: *natural range 0 to MAX_COUNT;
> * signal Done_Counting: std_ulogic;
> begin
> * process(Clock)
> * begin
> * * if rising_edge(Clock) then
> * * * ------------
> * * * -- FSM logic
> * * * ------------
> * * * if (Reset = '1') then
> * * * * Current_State <= Idle;
> * * * else
> * * * * case Current_State is
> * * * * * when Idle =>
> * * * * * * -- Code to wait for event to start timing
> * * * * * when Start_Count =>
> * * * * * * if (Done_Counting = '1') then
> * * * * * * * Current_State <= Done;
> * * * * * * end if;
> * * * * * when Done =>
> * * * * * * -- Code to take us back to idle presumably
> * * * * end case;
> * * * end if;
>
> * * * ------------------------
> * * * -- Output signal counter
> * * * ------------------------
> * * * if ((Current_State /= Start_Count)
> * * * or (Counter = MAX_COUNT) then
> * * * * Counter <= 0;
> * * * else
> * * * * Counter <= Counter + 1;
> * * * end if;
> * end process;
>
> Done_Counting <= '1' when (Counter = MAX_COUNT) else '0';
Thanks for your post. I mostly agree with you, I'd put the counter
along with the fsm logic, as opposed to the datapath code placeholder,
mostly because the 'passing data' never interacts with the counter, it
is more like an 'fsm helper', so it is more readable if it described
nearby. I however feel that having the control logic separate is
usually helpful. This can happen in any levels, and this does not
mean that there is no control logic in the blocks of code that make up
what one normally considers the datapath. For example, a filter that
is receiving a BT656 video stream and only outputs active video
(filtering out blanking, etc) is seen by a higher level as a datapath
block (filter), but its description may actually be composed of a
datapath/fsm type of design as well. On a related note, lets say that
when one block finishes a task, another block must be activated. One
might feel tempted to connect the done signal of one to the start
signal of the other, and the fsm wouldn't even see that net. However,
I feel that that connection is more an optimization step than good
design practice, simply because a future requirement might introduce
additional conditions - when b1 finishes, then b2 starts, UNLESS blah
blah blah - and inserting this new condition can be more easily added
by modifying the fsm's code, than having to modify the datapath. Of
course, there can be many exceptions, and I share the pragmatic point
of view of just wirte code what works, although I sometimes find
myself relocating code so that it becomes more modular and reusable,
and somehow matches the mental structure that I have of the design,
sometimes even at the slight expense of efficiency.