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.

Help me analyze this Verilog code

Status
Not open for further replies.

shaiko

Advanced Member level 5
Joined
Aug 20, 2011
Messages
2,644
Helped
303
Reputation
608
Reaction score
297
Trophy points
1,363
Activity points
18,302
I need to analyze the following Vrilog code...

Code:
module SPORT_BUS(
            OSC_CLK,
            TSCLK0,         //4MHz DSP clk     
            TFS0,           //DSP stobe 
            DT0PRI,         //DSP Serial data input
            REC_DATA,       //8bit receive  data buffer
            RSCLK0,         //4MHz FPGA clk
            RFS0,           //FPGA storbe
            DR0PRI,         //FPGA Serail data output
            TR_DATA,        //8bit transmit data buffer
            RESET,          //global reset
            START,          //start tx
            NEW_REC,        //New data is ready
            READY
            );


input           OSC_CLK;
input           TSCLK0;              
input           TFS0;           
input           DT0PRI;
input           RESET;
input           START;         
input   [7:0]   TR_DATA;        

output          RSCLK0;         
output          RFS0;           
output          DR0PRI;
output          NEW_REC;
output  [7:0]   REC_DATA;
output          READY;


wire            OSC_CLK;
wire            TSCLK0;             
wire            TFS0;            
wire            DT0PRI;         
wire            RESET;      
wire            RSCLK0;         
wire            RFS0;           
wire            START;
wire            NEW_REC;         
wire    [7:0]   TR_DATA;     


reg     [7:0]   REC_DATA;
reg     [13:0]  state1;
reg     [13:0]  state2;
reg             DR0PRI;
reg             READY;
reg             tsclk0_sampled2;
reg             tsclk0_sampled;

//assign  RSCLK0  =   TSCLK0;
assign  RSCLK0  =   tsclk0_sampled;
//                        s
//                        t
//                        r--1hot--43210;
parameter   idle    = 14'b00000000000000;
parameter   tx1     = 14'b11000000000010;
parameter   tx2     = 14'b00100000000011;
parameter   tx3     = 14'b00010000000100;
parameter   tx4     = 14'b00001000000101;
parameter   tx5     = 14'b00000100000110;
parameter   tx6     = 14'b00000010000111;
parameter   tx7     = 14'b00000001001000;
parameter   tx8     = 14'b00000000101001;

parameter   rx_dly  = 14'b00000000010011;
parameter   rx1     = 14'b01000000001010;
parameter   rx2     = 14'b00100000001011;
parameter   rx3     = 14'b00010000001100;
parameter   rx4     = 14'b00001000001101;
parameter   rx5     = 14'b00000100001110;
parameter   rx6     = 14'b00000010001111;
parameter   rx7     = 14'b00000001010000;
parameter   rx8     = 14'b10000000110001;

always  @(posedge   OSC_CLK or negedge  RESET)
    if(!RESET)
        begin
            tsclk0_sampled  <=  1'h0;
            tsclk0_sampled2 <=  1'h0;
        end
    else
        begin
            tsclk0_sampled2 <=  TSCLK0;  
            tsclk0_sampled  <=  tsclk0_sampled2;  
        end
//RX SPORT section   
     
always @(negedge    /*TSCLK0*/tsclk0_sampled2 or negedge   RESET)
    if(!RESET)
        begin
            state2  <=  14'h0;
        end
    else
        begin
            case(state2)
                idle:
                        if(TFS0)
                            state2   <=  rx_dly;
                        else
                            begin
                                state2  <=  idle;
                            end
                            
                rx_dly: state2   <=  rx1;
                rx1:    state2   <=  rx2;
                rx2:    state2   <=  rx3;
                rx3:    state2   <=  rx4;
                rx4:    state2   <=  rx5;
                rx5:    state2   <=  rx6;
                rx6:    state2   <=  rx7;
                rx7:    state2   <=  rx8;
                rx8: begin
                          if(TFS0)
                            state2   <=  rx_dly;
                          else
                            state2   <=  idle;
                        end    
                default:  state2   <=  idle;
            endcase
        end

//TX SPORT section

always @(posedge    RSCLK0 or negedge   RESET)
    if(!RESET)
        begin
            state1  <=  14'h0;
            DR0PRI  <=  1'h0;
            READY   <=  1'h1;
        end
    else
        begin
            case(state1)
                idle:   begin
                            READY   <=  1'h1;
                            if(START)
                                begin
                                    state1   <=  tx1;
                                end
                            else
                                begin
                                    state1  <=  idle;
                                    DR0PRI  <=  1'h0;
                                end
                        end    
                tx1:    begin
                			READY   <=  1'h0;
                            state1  <=  tx2;
                			DR0PRI  <=  TR_DATA[7];
                		end
                tx2:    begin
                			state1   <=  tx3;
                			DR0PRI  <=  TR_DATA[6];
                		end
                tx3:    begin
                			state1   <=  tx4;
                			DR0PRI  <=  TR_DATA[5];
                		end
                tx4:    begin
                			state1   <=  tx5;
                			DR0PRI  <=  TR_DATA[4];
                		end
                tx5:    begin
                			state1   <=  tx6;
                			DR0PRI  <=  TR_DATA[3];
                		end
                tx6:    begin
                			state1   <=  tx7;
                			DR0PRI  <=  TR_DATA[2];
                		end
                tx7:    begin
                			state1   <=  tx8;
                			DR0PRI  <=  TR_DATA[1];
                		end
                tx8:    begin
                		    DR0PRI  <=  TR_DATA[0];
                		  /*if(START)
                            begin
                              state1   <=  tx1;
                            end
                          else
                            begin
                                state1  <=  idle;
                            end*/
                		    state1  <=  idle;
                        end
                default:  state1   <=  idle;
            endcase
        end


assign  RFS0    =   state1[13];
assign  NEW_REC =   state2[13];  

// RX

    always  @(posedge   state2[12])
        begin
            REC_DATA[7]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[11])
        begin
            REC_DATA[6]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[10])
        begin
            REC_DATA[5]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[9])
        begin
            REC_DATA[4]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[8])
        begin
            REC_DATA[3]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[7])
        begin
            REC_DATA[2]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[6])
        begin
            REC_DATA[1]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[5])
        begin
            REC_DATA[0]  <=  DT0PRI;
        end
        
endmodule

A few questions:
1. What is the purpose of rx1,rx2,rx3,rx4,rx5,rx6,rx7,rx8,rx_dly,idle ? Why are they parameterized ?
2. As I see : "tsclk0_sampled2" is sampled using the "OSC_CLK" signal. However, it's also used in the second "always" under the "negedge" statement. this will yield a gated clock - correct ?
 

Looks like a FSM.

1. All the rx1...rx8 etc you mention are the states of the FSM. They are parameterized because that's a convenient way to define your FSM states.

Code:
//                        s
//                        t
//                        r--1hot--43210;
parameter   idle    = 14'b00000000000000;
parameter   tx1     = 14'b11000000000010;

And as you can see it's a combination of 5-bit binary number in the LSB, then some 1-hot state encoding, and the MSB looks like a set/reset or somesuch.

Code:
assign  RFS0    =   state1[13];
assign  NEW_REC =   state2[13];

That's where the "set/reset or somesuch" gets assigned to signals to be used elsewhere. Could be a strobe, what with the "str" now that I think about it.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
And as you can see it's a combination of 5-bit binary number in the LSB, then some 1-hot state encoding, and the MSB looks like a set/reset or somesuch.
I've never seen such FSM written in VHDL...
VHDL uses simple enumaration for the states. why Verilog is different?
 

dave_59,

I'm used to describing state machines in VHDL.
I often use the registered Meally type with a single synchronous process.

Can I do the same thing with Verilog? I mean describing a registered Mealy FSM with a single "always" block?
 

ok,
another question.

please look at the following section of code:

Code:
    always  @(posedge   state2[12])
        begin
            REC_DATA[7]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[11])
        begin
            REC_DATA[6]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[10])
        begin
            REC_DATA[5]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[9])
        begin
            REC_DATA[4]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[8])
        begin
            REC_DATA[3]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[7])
        begin
            REC_DATA[2]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[6])
        begin
            REC_DATA[1]  <=  DT0PRI;
        end
    
    always  @(posedge   state2[5])
        begin
            REC_DATA[0]  <=  DT0PRI;
        end

It will create a lot of gated clocks - right ?
 

I don't think you get gated clocks, I am not 100% certain. The code is a bit dodgy IMHO. What I am pretty sure about is that whoever wrote this verilog code did not intend it as gated clocks.

If you look at this bit:


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//                        r--1hot--43210;
parameter   idle    = 14'b00000000000000;
parameter   tx1     = 14'b11000000000010;
 
// ... snip ...
 
parameter   rx_dly  = 14'b00000000010011;
parameter   rx1     = 14'b01000000001010;
parameter   rx2     = 14'b00100000001011;
parameter   rx3     = 14'b00010000001100;
parameter   rx4     = 14'b00001000001101;
parameter   rx5     = 14'b00000100001110;
parameter   rx6     = 14'b00000010001111;
parameter   rx7     = 14'b00000001010000;
parameter   rx8     = 14'b10000000110001;



Then you see that state2[12] ... state2[5] correspond with those rx1 .. rx8 states. Them thar be one-hot encoded states.

Now while those @posedge's probably work, I don't think it's the best idea ever. IMO a better practice is to write it like so:



Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
always @(posedge clock) begin
    case(1'b1) begin // synthesis parallel_case
      state2[12]: REC_DATA[7]  <=  DT0PRI;
      state2[11]: REC_DATA[6]  <=  DT0PRI;
      state2[10]: REC_DATA[5]  <=  DT0PRI;
      state2[9] : REC_DATA[4]  <=  DT0PRI;
      state2[8] : REC_DATA[3]  <=  DT0PRI;
      state2[7] : REC_DATA[2]  <=  DT0PRI;
      state2[6] : REC_DATA[1]  <=  DT0PRI;
      state2[5] : REC_DATA[0]  <=  DT0PRI;
    endcase
end



That does the same thing as what I think is intended here, but keeps things a bit more readable. And for bonus points you can parameterize things so you get this:



Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
parameter RX1=12;
// ...
parameter RX8=5;
 
always @(posedge clock) begin
    case(1'b1) begin // synthesis parallel_case
      state2[RX1]: REC_DATA[7]  <=  DT0PRI;
      state2[RX2]: REC_DATA[6]  <=  DT0PRI;
      state2[RX3]: REC_DATA[5]  <=  DT0PRI;
      state2[RX4]: REC_DATA[4]  <=  DT0PRI;
      state2[RX5]: REC_DATA[3]  <=  DT0PRI;
      state2[RX6]: REC_DATA[2]  <=  DT0PRI;
      state2[RX7]: REC_DATA[1]  <=  DT0PRI;
      state2[RX8]: REC_DATA[0]  <=  DT0PRI;
    endcase
end



Note that the RX1 .. RX8 are suspiciously much like the lower case rx1 ... rx8. So I would NOT actually use this particular bit of code verbatim in your original code. This is more so you get the idea.

Edit: Oh yeah, and don't forget those "synthesis parallel_case", otherwise you just might get Priority Encoders of Slowness & Suffering. To see what that does see the XST user guide.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
It looks like the coder wanted to implement 2 simple shift registers with 2 complex and unorthodox FSMs

- - - Updated - - -

I don't think you get gated clocks
What else can you get out of 8 unrelated always blocks with a signal other then a clock triggering the FF ?
 

What else can you get out of 8 unrelated always blocks with a signal other then a clock triggering the FF ?

Answer: Whatever the hell the synthesis tool comes up with this time. :p

But if you really want to know, just plug it in and synthesize it.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top