Electronic – Accessing same variables in Verilog on different clocks

clocksystem-verilogverilog

I have a 50Mhz master clock clk and from that I have a derived baudClock clock which runs at 9600bps.

I have a transmitter module that I want to follow a state machine flow every baudClock.

The transmitter module receives strings from an external module/testbench and puts them into a queue. I want the state machine to take an item from the queue and then reduce queueCount by one.

On the other hand, I would like to be able to add an item to the queue on a clk cycle.

I cannot implement something such as that below because I would then be assigning queueCount from 2 always processes (resulting in multiple driver errors).

always_ff @(posedge clk )
begin
  if( addToQueue )
  begin
    if( queueCount < MAX_ELEMENTS )
    begin
      textQueue[ queueCount ] = myString;
      queueCount ++;
    end
  end
end

always_ff @(posedge baudClock )
begin
  unique case( state )
    IDLE         : HandleIdle();
    GETNEXT      : HandleGetNextString();  // Decreases queueCount
    SENDSTART    : HandleSendStart();
    SENDDATA     : HandleSendData();
    SENDBYTEDONE : HandleSendByteDone();
  endcase
end  

How would I go about doing this? ie. What's the best way to share variables in reading/writing or producer/consumer scenarios?

Best Answer

In comments you said this is for implementation in an FPGA.

In that case, you should reconsider your architecture.

Instead of dividing down your 50 MHz master clock and having a second 9600 Hz clock, use the 50 MHz clock to drive your 9600 Hz logic, but use a strobe signal to enable that logic.

reg str9600;
reg [12:0] str_ct;

always @(posedge clk) begin
    // Generate 9600 baud strobe
    if (reset) begin
        str_ct <= 0;
        str9600 <= 0;
    end
    else if (str_ct == 5208) begin
        str_ct <= 0;
        str9600 <= 1;
    end
    else begin
        str_ct <= str_ct + 1;
        str9600 <= 0;
end

always @(posedge clk) begin
   // Do 9600 baud operations when enabled by strobe
   if (reset) 
        // reset stuff
   else if(str9600) 
        // do 9600 baud stuff
end

always @(posedge clk) begin
    // do 50 MHz stuff
    // queue management goes here
end

Now your queue becomes part of the 50 MHz logic, with the str9600 signal as an input, telling it whether something can be pulled out of the queue, but able to add to the queue on any 50 MHz clock edge.