Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

Driving a module output with a reg?

Hello,

I'm trying to determine the best way to gain access to the output of a module which is simply a wire - who in it's own module is driven by a continuous assignment statement.

The project is an implementation of the DES algorithm (courtesy OpenCores) with communication to and from the PC.

Here is the code:


module receiving_test(sysclk, rxd, txd, LEDG, LEDR);
 
input sysclk, rxd;
output txd;
wire receiving_complete, isTransmitting;
output reg  LEDG;
output reg  LEDR;
 
reg begin_transmit;
reg  tbyte;
 
wire  rbyte;
 
parameter FIRST_BYTE = 0, GET_BYTES = 1, BEGIN_ENC = 2, CHECK_ENC_STATUS = 3, BEGIN_TRANSMISSION = 4, SEND_BYTES = 5;
 
reg  state;
integer bytes_remaining;
 
reg  sel;
reg  plain_text;
reg  cipher_text;
wire  cipher_net;
 
uart uart1(
    .clk(sysclk),
    .rx(rxd),
    .tx(txd),
    .transmit(begin_transmit),
    .tx_byte(tbyte),
    .received(receiving_complete),
    .rx_byte(rbyte),
    .is_transmitting(isTransmitting)
    );
 
des des1(
     .clk(sysclk),
     .key(56'h0),
     .roundSel(sel),
     .decrypt(1'b0),
     .desIn(plain_text),
     .desOut(cipher_net)
     );
 
always @(posedge sysclk)
    begin
        cipher_text = cipher_net;
        begin_transmit = 1'b0;
        case(state)
            FIRST_BYTE: begin
                if(receiving_complete) begin
                   plain_text = rbyte;
                    plain_text = plain_text >> 8;
                    bytes_remaining = 7;
                    state = GET_BYTES;
                end
            end
            GET_BYTES: begin
                if(receiving_complete) begin
                    plain_text = rbyte;
                    bytes_remaining = bytes_remaining - 1;
                    if(bytes_remaining == 0) begin
                        state = BEGIN_ENC;
                    end else begin
                        plain_text = plain_text >> 8;
                    end
                end
            end
            BEGIN_ENC: begin
                sel = 4'b0;
                state = CHECK_ENC_STATUS;
            end
            CHECK_ENC_STATUS: begin
                sel = sel + 1;
                if(sel == 15) begin
                    LEDG = cipher_text;
                    LEDR = cipher_text;
                    state = BEGIN_TRANSMISSION;
                end
            end
            BEGIN_TRANSMISSION: begin
                tbyte = cipher_text;
                begin_transmit = 1'b1;
                cipher_text = cipher_text >> 8;
                bytes_remaining = 7;
                state = SEND_BYTES;
            end
            SEND_BYTES: begin
                if(!isTransmitting) begin
                    tbyte = cipher_text;
                    begin_transmit = 1'b1;
                    bytes_remaining = bytes_remaining - 1;
                    if(bytes_remaining == 0) begin
                        state = FIRST_BYTE;
                    end else begin
                        cipher_text = cipher_text >> 8;
                    end
                end
            end
        endcase
    end
 
endmodule

And here is the error I'm hoping to correct:

Warning (10034): Output port "LEDG" at receiving_test.v(6) has no driver

Warning (10034): Output port "LEDR" at receiving_test.v(7) has no driver

.... among various others that I was able to determine after some research are consequences of these two. Basically, the output desOut from the DES module is not being properly driven.

I'm aware that it is illegal to hook-up the output of an instantiated module directly to a 'reg', so I tried the work-around of:

1) first declaring a wire in the top-level module

2) Connecting this wire to the desOut output in the instantiation

3) Assigning the output of this wire to a reg at the posedge of the clock

-- This didn't work.

I need to be able to sample the value at desOut, but I'm unable to do so because it has no drive strength - and I'm not sure how to supply it with any!

Any suggestions on this issue, or the code in general for that matter - are greatly appreciated!

P.S. Each module has been tested separately, and the RS232 transmitter and receiver together. I'm quite sure that this should be mostly working if I can figure out this issue.

P.P.S - I've also read in many Verilog references that in procedural blocks it is best practice to use non-blocking assignment. However, using these I was not getting the intended behavior.

After looking at some state machine examples similar in nature to what I'm trying to achieve - I notices these were actually using blocking assignments. After trying this out, blocking assignments did indeed give me the functionality I was looking for. This seems to conflict - can anyone shed some light as to why this might be?

Thanks!

Kristin

5 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Warning (10034): Output port "LEDG" at receiving_test.v(6) has no driver

    Warning (10034): Output port "LEDR" at receiving_test.v(7) has no driver

    --- Quote End ---

    The warning means that the code assigning values to the LED ports is unreachable. It must be an unequivocal condition.

    In this case (sel == 16) is always false, because sel has a range of 0-15.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Whoops.. that should actually have been 15. I changed it for debugging and forgot to change it back.

    With the condition set to if( sel == 15) the problem still persists.

    Can you see any other anamolies in the code?

    What exactly do you mean by uneqivocal condition?

    Thanks,

    Kristin
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I would simulate this logic to see if it steps through the statemachine as expected. If I had to guess the integer 'bytes_remaining' can never be set to 0 and as a result that trickles down to the CHECK_ENC_STATUS never being reachable. That was just a wild stab in the dark though, I'm not really following what's going on in the state machine since it's coded in a style that I typically avoid.

    By the way you should have reset conditions for your registers.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    @BadOmen: Thanks for the reply.

    Why is this typically a style that you avoid? I'm trying to learn best practices still.

    Also, why would the integer not be able to reach 0 - should I use registers for this value instead?

    Thanks,

    Kristin
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    My way might be a little confusing at first. I typically one-hot encode my statemachines.... and I don't write them as giant case statements either which throws people off who code statemachines the way they learned in school.

    The way I code your sort of statemachine would be:

    - 3 bit counter (same state encoding)

    - counter enable driven by an assign statement that determines when to move to the next state

    - bunch of assign statements for all the outputs (or register enables depending on whether those outputs need to be captured by a register

    That only works for sequential state machines, for non sequential I typically one-hot encode them and build the state transistion logic manually. If the state machine becomes too big for one-hot encoding... well in my opinion that means you haven't though it through enough and should consider assembling smaller statemachines, and if that doesn't work then you probably have something that belongs in the software realm anyway (so Nios II would be an option).

    If you are wondering why I prefer this method it's mainly two reasons: 1) my coding style is to never put blocking operations in an always block, 2) I prefer to code without relying much on synthesis to optimize things for me.