Verilog - shift out several registers? - Page 1
Forum section: electronics / general

author: David Chamberlain
author_rank: Frequent Contributor
timestamp: April 14, 2018, 05:23:56 am
content: 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:reg [31:0] result_a;reg [31:0] result_b;reg [31:0] result_b;always @(posedge iCLK or posedge iRESET)beginif(iRESET) beginlr_cnt = 0;out_state <= 1;end else begincase (out_state)4'b0001 : oOUT = result_a;4'b0010 : oOUT = result_b;4'b0100 : oOUT = result_c;4'b1000 : oOUT = 0;endcaselr_cnt = lr_cnt + 1;if(lr_cnt == 0)beginout_state = out_state << 1;endendendI 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: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)beginif(iRESET) beginSPI_OUT <= 0;end else beginoOUT = SPI_OUT;SPI_OUT <= SPI_OUT < 1;endendThanksDavid.

author: radar_macgyver
author_rank: Frequent Contributor
timestamp: April 14, 2018, 05:47:37 am
content: 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.

author: David Chamberlain
author_rank: Frequent Contributor
timestamp: April 14, 2018, 06:24:12 am
content: 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:procedural assignment to a non-register result_a is not permitted. VERI-1100Done: error code 2The line in question is the first assignment to one of these registers, in another always block.Code: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.

author: radar_macgyver
author_rank: Frequent Contributor
timestamp: April 14, 2018, 06:28:23 am
content: 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).

author: David Chamberlain
author_rank: Frequent Contributor
timestamp: April 14, 2018, 06:38:50 am
content: ok, it seems to like it better if I wire it backwards and index in to the mapping.Code: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)beginif(iRESET) beginlr_cnt = 0;endelse beginoOUT = SPI_OUT;lr_cnt = lr_cnt + 1;endend

author: David Chamberlain
author_rank: Frequent Contributor
timestamp: April 14, 2018, 07:04:03 am
content: And better still if I just follow your advice and just copy the registers to an SPI_OUT register.Code: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)beginif(iRESET) beginSPI_OUT <= {result_c, result_b, result_a};endelse beginoOUT <= SPI_OUT;SPI_OUT <= SPI_OUT < 1;endend