Author Topic: Verilog - shift out several registers?  (Read 1270 times)

0 Members and 1 Guest are viewing this topic.

Offline David ChamberlainTopic starter

  • Regular Contributor
  • *
  • Posts: 249
Verilog - shift out several registers?
« on: April 14, 2018, 05:23:56 am »
Hi, can anyone with any understanding (because mine is limited) of Verilog or HDL in general help me find a better way to do this?

Some processing is done and I provide a SPI like interface to shift out the results. The first approach was to use an index for each bit in the register and out_state to select the register as counting of clicks goes.

This method works, I'm just wondering if it can be approached in a different way?

Code: [Select]
reg [31:0] result_a;
reg [31:0] result_b;
reg [31:0] result_b;

always @(posedge iCLK or posedge iRESET)
begin
if(iRESET) begin
lr_cnt = 0;
out_state <= 1;
end else begin
case (out_state)
4'b0001 : oOUT = result_a[lr_cnt];
4'b0010 : oOUT = result_b[lr_cnt];
4'b0100 : oOUT = result_c[lr_cnt];
4'b1000 : oOUT = 0;
endcase

lr_cnt = lr_cnt + 1;
if(lr_cnt == 0) begin
out_state = out_state << 1;
end
end
end


I was thinking about the following idea It's a lot simpler but want to check that if another part of the design causes result_b to overflow it will not crash into result_c? But I guess it should not because it is not wired like that.

Code: [Select]
reg [95: 0] SPI_OUT;
wire [31:0] result_a = SPI_OUT[31:0];
wire [31:0] result_b = SPI_OUT[63:32];
wire [31:0] result_c = SPI_OUT[95:64];

always @(posedge iCLK or posedge iRESET)
begin
if(iRESET) begin
SPI_OUT <= 0;
end else begin
oOUT = SPI_OUT[95];
SPI_OUT <= SPI_OUT < 1;
end
end


Thanks

David.
« Last Edit: April 14, 2018, 06:19:32 am by David Chamberlain »
 

Offline radar_macgyver

  • Frequent Contributor
  • **
  • Posts: 698
  • Country: us
Re: Verilog - shift out several registers?
« Reply #1 on: April 14, 2018, 05:47:37 am »
If you, for example, increment result_b somewhere else in the design and its value is 2^32-1, it will wrap around to zero. The hardware synthesized in this case would be a 32-bit counter, there's no way the carry from the msb of result_b gets tied to result_c.

The second example should be functionally equivalent to the first. However, it's probably not what you want. Your SPI shift register should be separate from result_a, etc, and get copied over when the SPI bus CS_B is high (bus not active). As soon as CS_B becomes active, data from result_a, result_b and result_c should be copied into the shift register, and then clocked out in response to SCK. This way, the contents of result_a etc are not modified when the SPI master tries to read the data.
 

Offline David ChamberlainTopic starter

  • Regular Contributor
  • *
  • Posts: 249
Re: Verilog - shift out several registers?
« Reply #2 on: April 14, 2018, 06:24:12 am »
Thanks, and sorry my second example had a mistake.
Thse lines I had it as SPI_IN.. should be wire [31:0] result_a = SPI_OUT[31:0];

Anyway when I synthesize the second example I get the following error.
Code: [Select]
procedural assignment to a non-register result_a is not permitted. VERI-1100
Done: error code 2

The line in question is the first assignment to one of these registers, in another always block.
Code: [Select]
result_a <= 0;
I guess it does not like setting the register through the wires?

If so then I'll need to copy them over like you say, but this is not actually something I needed because the results are junk once computed so I did not mind if the shift out destroyed them.
 

Offline radar_macgyver

  • Frequent Contributor
  • **
  • Posts: 698
  • Country: us
Re: Verilog - shift out several registers?
« Reply #3 on: April 14, 2018, 06:28:23 am »
Using 'register' implies a flip flop, so the two ways to store the value is using the D input and a clock pulse, or using the asynchronous set/reset. Neither way allows you to do so without some sort of qualification (that's what the always block is for in Verilog, or the rising_edge construct in VHDL).
 

Offline David ChamberlainTopic starter

  • Regular Contributor
  • *
  • Posts: 249
Re: Verilog - shift out several registers?
« Reply #4 on: April 14, 2018, 06:38:50 am »
ok, it seems to like it better if I wire it backwards and index in to the mapping.

Code: [Select]
reg [31:0] result_a;
reg [31:0] result_b;
reg [31:0] result_c;
wire [95: 0] SPI_OUT = {result_c, result_b, result_a};

always @(posedge iCLK or posedge iRESET)
begin
if(iRESET) begin
lr_cnt = 0;
end else begin
oOUT = SPI_OUT[lr_cnt];
lr_cnt = lr_cnt + 1;
end
end
 

Offline David ChamberlainTopic starter

  • Regular Contributor
  • *
  • Posts: 249
Re: Verilog - shift out several registers?
« Reply #5 on: April 14, 2018, 07:04:03 am »
And better still if I just follow your advice and just copy the registers to an SPI_OUT register.

Code: [Select]
reg [95: 0] SPI_OUT;
reg [31:0] result_a;
reg [31:0] result_b;
reg [31:0] result_c;

always @(posedge iCLK or posedge iRESET)
begin
if(iRESET) begin
SPI_OUT <= {result_c, result_b, result_a};
end else begin
oOUT <= SPI_OUT[95];
SPI_OUT <= SPI_OUT < 1;
end
end
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf