Author Topic: Verilog Using pos/negedge as a register?  (Read 10032 times)

0 Members and 1 Guest are viewing this topic.

Offline logictomTopic starter

  • Supporter
  • ****
  • Posts: 336
  • Country: au
Verilog Using pos/negedge as a register?
« on: April 08, 2011, 10:05:42 pm »
I've only been learning Verilog for the last couple of weeks but I'm stumped!
I'm trying to write a simple SPI master and want to include a basic register which controls which mode it is in. Idle clock polarity and edge triggering.

What I want to do is something like this:
reg x;
if(y) x = posedge;
else x = negedge;
always @ (x clk)

But I can't use posedge as it's a reserved keyword, there is probably a simple way to do this or a completely different way but I can't find anything on this.
Any help or suggestions are always appreciated :)

------------
Oh and did I mention I hate Verilog? :P It's driving me mad with errors all the time, any good resources would also be a great help :)
« Last Edit: April 08, 2011, 10:10:35 pm by logictom »
 

Offline Balaur

  • Supporter
  • ****
  • Posts: 525
  • Country: fr
Re: Verilog Using pos/negedge as a register?
« Reply #1 on: April 08, 2011, 11:08:54 pm »
I'm sorry, but I have some difficulty in understanding your terminology (Idle clock polarity?) and your example.
You cannot assign an event (posedge or negedge) to a signal. You assign a value. If the signal was at a different value, then yes, you will have a transition.

Please allow me to rephrase my way and ask you whether you want:
1) a continuous (combinational) assignment such as
Code: [Select]
wire x;
assign x = ~y;
or
Code: [Select]
wire x;
assign x = (condition) ? 0:1;
or
Code: [Select]
reg x;
always @(y) begin
  x = ~y;
  ...
end

2) Or maybe you want a registered signal that will only change on the latching edge of the clock and will be synthesized as a flip-flop:

Code: [Select]
reg x;
always @(posedge clk) begin
  x = ~y;
  ...
end

(I have assumed that y is a signal, but you can use if cases as well)

Cheers,
Dan
« Last Edit: April 08, 2011, 11:17:35 pm by Balaur »
 

Offline logictomTopic starter

  • Supporter
  • ****
  • Posts: 336
  • Country: au
Re: Verilog Using pos/negedge as a register?
« Reply #2 on: April 08, 2011, 11:49:20 pm »
Hi Dan, thanks for replying.
A little more info: I am trying to create a SPI master which in the case of a microcontroller would usually have a register for setting up the mode, clock frequency and other bits and bobs.

The modes are defined with attributes: High/Low clock when idle, data transfer on rising/falling edge.

ModePolarityEdge
0
0
0
1
0
1
2
1
0
3
1
1

The master I am attempting to create has a register to store the mode, what I want to do is be able to read this register and create an always @ block that will be triggered on a rising or falling edge determined by the register value.

The always statement will contain the logic to shift out the data on the corresponding edge.

The example I gave was trying to use an if to determine the state of the register and set the edge in the always statement. Y being the register value and X just being something to hold the pos/negedge definition.

Hopefully that has cleared it up? :)
I'm new to verilog and I'm still trying to get out of the sequential flow / C programming mind set  ???
 

Offline joelby

  • Frequent Contributor
  • **
  • Posts: 634
Re: Verilog Using pos/negedge as a register?
« Reply #3 on: April 09, 2011, 04:01:25 am »
Normally for something slow (relative to the system clock) like SPI you would use a counter to divide the clock, typically to double the SPI frequency, and then set the SPI clock high and low on alternate (positive) edges of that master clock. Don't try to mix positive and negative edges in a design unless you have a good reason to do so.
 

Offline Balaur

  • Supporter
  • ****
  • Posts: 525
  • Country: fr
Re: Verilog Using pos/negedge as a register?
« Reply #4 on: April 09, 2011, 07:54:42 am »
OK, I think I have a better understanding.

As suggested by joel you can go with a clock divider and a clock counter.

Or, a bit closer to what you have in mind, here is an example of sampling on either edge of the clock:
Code: [Select]
module test(
    input clk,
    input mode,
    input in,
    output out
    );

reg pos_sample;
reg neg_sample;
wire sample;

always @(posedge clk) pos_sample = in;
always @(negedge clk) neg_sample = in;

assign sample = mode ? neg_sample : pos_sample;

// Continous assignment
assign out = sample;

// Registered
// always @(posedge clk) out = sample;

endmodule

This code corresponds to two flip-flops, driven by either positive or negative edges of the clock and a mux to chose one of the sampled values. I would go with the registered sample output.
Depending on your implementation target, the proposed idea is good (FPGA) or bad (ASIC)
 

Offline joelby

  • Frequent Contributor
  • **
  • Posts: 634
Re: Verilog Using pos/negedge as a register?
« Reply #5 on: April 09, 2011, 08:21:19 am »
I'm reluctant to ever mix posedge and negedge, so I would do something like this:

input wire sample_edge;
output wire spi_clock;
input wire spi_miso;
output reg [15:0] data_out;


reg spi_clock_reg = 0;
assign spi_clock = spi_clock_reg;

reg state;

always @(posedge spi_clock_4x)
begin
 if (state)
   spi_clock_reg <= ~spi_clock_reg;
 else begin

 if (spi_clock_reg && sample_edge)
 begin
   data_out[15:1] <= data_out[14:0];
   data_out[0] <= spi_mosi;
 end else if (~spi_clock_reg && ~sample_edge)
   data_out[15:1] <= data_out[14:0];
   data_out[0] <= spi_mosi;
 end

 state <= ~state;
end

This way, the data is sampled 1/4 of a period after the clock transition.
 

Offline logictomTopic starter

  • Supporter
  • ****
  • Posts: 336
  • Country: au
Re: Verilog Using pos/negedge as a register?
« Reply #6 on: April 09, 2011, 10:16:56 pm »
Thank you both for the help. As usual I'm juggling 101 things so keep going back and forth on this.

I running into another problem, I am trying to read in some parallel data and the clock is out out serially.
If I do something like the following I get an error about trying to drive from two always blocks
Code: [Select]
input [7:0] datain;
output spi_clk;
output spi_data;

always @(datain)
datareg = datain

always @(posedge spi_clk)
begin
spi_data = datareg;
datareg = datareg << 1;
end
I'd need to add some sort of control to only read in data once it's finished sending out the last byte but that's for later once I've actually got something coming out the thing.

Sorry this is probably really easy stuff but I'm racking my brains trying to figure this one out....
 

Offline joelby

  • Frequent Contributor
  • **
  • Posts: 634
Re: Verilog Using pos/negedge as a register?
« Reply #7 on: April 10, 2011, 01:09:04 am »
Unless you're doing combinatorial logic, always blocks should only be triggered by clocks, and occasionally an asynchronous reset if you have a good reason to use one. You should use write enables and busy flags to control how the module works with other parts of the system.

input wire reset;
input [7:0] datain;
input clk;
input write_enable;
output reg spi_data;

reg [4:0] state = 0;
reg [7:0] datareg;

always @(posedge clk)
begin
  if (reset) begin
    state <= 0;
    spi_data <= 0; 
  end else

  case (state)
  0:
    if (write_enable) begin
      datareg <= datain;
      state <= 1'b1;
    end

  9: begin
    spi_data <= 0;
    state <= 0;
  end

  default: begin
    spi_data <= datareg[7];
    datareg[7:1] <= datareg[6:0];
    state <= state + 1'b1;
  endcase
end

This does:
- After reset, go to the idle state (0).
- When write_enable is asserted, save datain to datareg and proceed to transmit states (1-8).
- states 1-8 are captured by the default: block. This is a simple way to use the state register as a counter. The other option would be to use a separate counter register. For eight bits, shift the MSB of data_reg into spi_data, and shift the rest up one bit.
- At state 9, go back to idle state.

I don't think this will work as-is, but it should give you a bit of an idea. If you were generating the clock in this state machine, you'd want to run it at double the clock rate and then only change the MOSI bit every other cycle, at your desired clock edge and polarity.
 

Offline logictomTopic starter

  • Supporter
  • ****
  • Posts: 336
  • Country: au
Re: Verilog Using pos/negedge as a register?
« Reply #8 on: April 17, 2011, 06:25:07 pm »
Sorry for the late response. Thanks for the pointers joel, that was exactly the info I needed to get this off the ground, I have finished up the code and it looks good from the simulations, hopefully I'll get a chance to test it out in the next couple of weeks.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf