I have a line of data of 264 bits in memory buffer written using Verilog HDL.
buffer[2]=264'b000100000100001000000000001000000000000001000001000000000000000000000000000000000000100000010000010000100000000000100000000010000100001100000000000000000000000000000000000010000001000001000010000000000010000000000000010001010000000000000000000000000000000000001000;
I want to transfer 10 bits within the above raw from buffer[2][147:138] bits to buffer[2][59:50], then transfer buffer[2][235:226] bits into buffer[2][147:138]
I try to do this using XOR but it dose not work
buffer[2][59:50]=buffer[2][59:50]^buffer[2][147:138];
buffer[2][147:138]=buffer[2][59:50]^buffer[2][147:138];
buffer[2][59:50]=buffer[2][59:50]^buffer[2][147:138];
buffer[2][235:226]=buffer[2][235:226]^buffer[2][147:138];
buffer[2][147:138]=buffer[2][235:226]^buffer[2][147:138];
buffer[2][235:226]=buffer[2][235:226]^buffer[2][147:138];
How can I do this without using non-blocking assignment ?
You can swap with concatenations, no xor required:
{buffer[2][147:138],buffer[2][59:50]} = {buffer[2][59:50],buffer[2][147:138]};
{buffer[2][235:226],buffer[2][147:138] = {buffer[2][147:138],buffer[2][235:226]};
Your title says swap, but your description says transfer. To transfer you can can still use the same approach:
{buffer[2][147:138],buffer[2][59:50]} = {buffer[2][235:226],buffer[2][147:138]}
// Or you can do this, beware order matters
buffer[2][59:50] = buffer[2][147:138];
buffer[2][147:138] = buffer[2][235:226];
Be careful where you do this in an always block. It can create a combinational feedback loop after synthesized if done incorrectly. The bits must first be assigned by a determinate value (ideally a flop) before doing the swap.
Just create a new variable to hold the new, rearranged, array. This should not generate any logic, you are just rearranging wires.
reg [263:0] reArrBuffer [0:2];
assign reArrBuffer =
'{buffer[0],
buffer[1],
{buffer[2][263:148], buffer[2][235:226], buffer[2][137:60], buffer[2][147:138], buffer[2][49:0]}
};
Note: You need ' in front of the first { to create an assignment pattern for an unpacked array. It can be removed if buffer and reArrBuffer is packed.
Related
I have an inferred latch problem after synthesis when I designed a simple dual port RAM block. Due to large code size, I have just embedded this always block code as follows:
integer i;
always_latch
begin
for (i=0;i<NUM_RAMS;i=i+1) begin
if (ena_t == 1) begin
w_addra_t[i] = w_addra[i];
end
else begin
w_addra_t[bank_addra[i]] = w_addra[i];
end
end
end
My RAM block includes NUM_RAMS numbers of banks. The addresses of respective input data are stored in w_addra.
Data with given w_addra addresses are scrambled into w_addra_t depend on the values of respective bank_addra (depend on access pattern) when ena_t = 0.
I tried to replace for loop with if...else, switch...case, generate but the problem is same. With different always block in my code that the left-side is with only w_addra_t[i] in both if.else of ena_t, there is no error.
I would like to get your suggestion if you have any idea. I did look for similar issue but getting no results.
Thanks very much :)
My guess is the entries for bank_addra are not guaranteed to be unique. If two or more entries hold the same values then an index hole is created for w_addra_t; which will infer a latch.
Here are three possible solution:
Functionally guaranteed that bank_addra entries will have unique values, then the synthesizer should not infer a latch. This can be challenging.
Move the address variation from the LHS to the RHS so that each index of w_addra_t is guaranteed to be assigned a value. Ex change w_addra_t[bank_addra[i]] = w_addra[i]; to w_addra_t[i] = w_addra[bank_addra_lookup[i]];.
Assign all entries of w_addra_t to a known value (constant, flip-flop, or deterministic value) before other logic. You can put this default assignment at the top of your always block (option 1 example) or above the logic where the latches were about to be inferred (option 2 example). This is the simplest solution to implement assuming it still satisfies relational requirements with your other code.
// NOTE: SystemVerilog supports full array assignments (Verilog requires a for-loop)
always_comb
begin
w_addra_t = '{default:'0}; // <-- default assignment : option 1
if (ena_t == 1) begin
w_addra_t = w_addra;
end
else begin
w_addra_t = w_addra_t_ff; // <-- default assignment : option 2
for (i=0;i<NUM_RAMS;i=i+1) begin
w_addra_t[bank_addra[i]] = w_addra[i];
end
end
end
always_ff #(posedge clk) begin
w_addra_t_ff <= w_addra_t; // assuming w_addra_t should hold it current values
end
TL;DR
always_latch is a SystemVerilog keyword to identify explicit latches. Some tools will auto-waive the warning when the keyword is used, but will throw an error/warning if the keyword is used and a latch is not detected.
If you know it should be combinational logic, then use the always_comb SystemVerilog keyword. With always_comb, if the synthesis detects a latch then it should report an error.
Read related question:
What is inferred latch and how it is created when it is missing else statement in if condition. Can anybody explain briefly?
I don't know if it will solve your problem by changing to
int i
always_comb
instead. Perhaps the tool gets sad when you use a 4-state variable like integer?
I am doing a computer architecture course on Coursera called
NandtoTetris and have been struggling with my 16-bit CPU design. The
course uses a language called HDL, which is a very simple Verilog like
language.
I have spent so many hours trying to iterate on my CPU design based on
the diagram below and I don't understand what I am doing wrong. I
tried my best to represent the fetch and execute mechanics. Does
anyone have any advice on how to solve this?
Here are the design and control syntax diagram links:
CPU IO high-level diagram:
Gate level CPU diagram:
Control instruction syntax:
Here is my code below:
// Put your code here:
// Instruction decoding:from i of “ixxaccccccdddjjj”
// Ainstruction: Instruction is 16-bit value of the constant that should be loaded into the A register
// C-instruction: The a- and c-bits code comp part, d- and j-bits code dest and jump(x-bits are ignored).
Mux16(a=outM, b=instruction, sel=instruction[15], out=aMUX); // 0 for A-instruction or 1 for a C-instruction
Not(in=instruction[15], out=aInst); // assert A instruction with op-code as true
And(a=instruction[15], b=instruction[5], out=cInst); // assert wite-to-A-C-instruction with op code AND d1-bit
Or(a=aInst, b=cInst, out=aMuxload); // assert Ainstruction or wite-to-A-C-instruction is true
ARegister(in=aMUX, load=cInst, out=addressM); // load Ainstruction or wite-to-A-C-instruction
// For C-instruction, a-bit determines if ALU will operate on A register input (0) vs M input (1)
And(a=instruction[15], b=instruction[12], out=Aselector); // assert that c instruction AND a-bit
Mux16(a=addressM, b=inM, sel=Aselector, out=aluMUX); // select A=0 or A=1
ALU(x=DregisterOut, y=aluMUX, zx=instruction[11], nx=instruction[10], zy=instruction[9], ny=instruction[8], f=instruction[7], no=instruction[6], zr=zr, ng=ng,out=outM);
// The 3 d-bits of “ixxaccccccdddjjj” ALUout determine registers are destinations for for ALUout
// Whenever there is a C-Instruction and d2 (bit 4) is a 1 the D register is loaded
And(a=instruction[15], b=instruction[4], out=writeD); // assert that c instruction AND d2-bit
DRegister(in=outM, load=writeD, out=DregisterOut); // d2 of d-bits for D register destination
// Whenever there is a C-Instruction and d3 (bit 3) is a 1 then writeM (aka RAM[A]) is true
And(a=instruction[15], b=instruction[3], out=writeM); // assert that c instruction AND d3-bit
// Programe counter to fetch next instruction
// PC logic: if (reset==1), then PC = 0
// else:
// load = comparison(instruction jump bits, ALU output zr & ng)
// if load == 1, PC = A
// else: PC ++
And(a=instruction[2], b=ng, out=JLT); // J2 test against ng: out < 0
And(a=instruction[1], b=zr, out=JEQ); // J1 test against zr: out = 0
Or(a=ng, b=zr, out=JGToutMnot)); // J0 test if ng and zr are both zero
Not(in=JGToutMnot, out=JGToutM; // J0 test if ng and zr are both zero
And(a=instruction[0], b=JGToutM, out=JGT);
Or(a=JLT, b=JEQ, out=JLE); // out <= 0
Or(a=JGT, b=JLE, out=JMP); // final jump assertion
And(a=instruction[15], b=JMP, out=PCload); // C instruction AND JMP assert to get the PC load bit
// load in all values into the programme counter if load and reset, otherwise continue increasing
PC(in=addressM, load=PCload, inc=true, reset=reset, out=pc);
It is tricky to answer these kinds of questions without doing the work for you, which isn't helpful to you in the long run.
Some general thoughts.
Consider each element in isolation (including the circles where signals come together).
Label each line between elements with a name. These will become internal control lines. It helps reduce the chances of confusion.
Be very careful about junk outputs. If you're not supposed to be putting valid data on outM, use a Mux to output false.
Potential gotcha: I seem to remember that it's a bad idea to use a design output (like outM) as an input to something else. Outputs should only be outputs. Right now you are sending the output of the ALU to outM and using outM as an input to other elements. I suggest you try outputting the ALU to a new signal "ALUout", and using that as the input for the other elements and (through a mux with false controlled by writeM) outM. But remember, writeM is an output! So the block that generates writeM needs to generate a copy of itself to use as the control to the mux. FORTUNATELY, a block can have multiple out statements!
For example, right now you're generating outM like this (I won't comment on whether it is wrong, I am just using it as an illustration):
And(a=instruction[15], b=instruction[3], out=writeM);
You can create a second output like this:
And(a=instruction[15], b=instruction[3], out=writeM, out=writeM2)
and then "clean" your outM like this:
Mux16(a=false,b=ALUout,sel=writeM2,out=outM);
Good luck!
I've got this code snip. It's a standard instantiation, but why is gen_srl16 used? I always thought SRL16E srl16e (... should be enough.
genvar i;
generate
for (i=0;i<WIDTH;i=i+1)
begin :
gen_srl16
SRL16E srl16e(
.Q(dataout[i]),
.A0(a[0]),.A1(a[1]),.A2(a[2]),.A3(a[3]),
.CE(write),.CLK(clk),.D(datain[i])); // CE -clock enable
end
endgenerate
In this situation gen_srl16 is just a name of a generate for-loop. It has nothing to do with submodule instantiation.
Following Verilog spec (IEEE Std 1800-2012, ch. 27.4):
Generate blocks in loop generate constructs can be named or unnamed (...) If the generate block is named, it is a declaration of an array of generate block instances. The index values in this array are the values assumed by the genvar during elaboration. This can be a sparse array because the genvar values do not have to form a contiguous range of integers. The array is considered to be declared even if the loop generate scheme resulted in no instances of the generate block.
How can I swap to values in an address. Currently I have 2 registers which contain the addresses. I then had 2 temporary variables which stores those addresses. I then loaded the values since I have the address. But I can not figure out how to swap the values. I am trying to do bubble sort. The code below is what I currently have
IF ;swapping condition
ST R2,idata ;temporily hold the smaller data
ST R1,imindata ;temporaily hold the larger data
ST R2,iminaddres ;store the values into that address
ST R2,iaddress ;finish the swaping of the two values
LD R1,iminaddres ;reput the address back into the register
LD R2,iaddres ;reput the address back into the register to be used for next cycle
How would you do it in C?
temp = a;
a = b;
b = temp;
Then understand there is a need to load those values from memory, which changes things a bit
tempa = a;
tempb = b;
b = tempa;
a = tempb;
then isolate the loads and stores
rega <= load(a);
regb <= load(b);
store(a) <= regb;
store(b) <= rega;
then implement that in assembly. This smells like a homework assignment so I wont do it for you.
If all you want to do is swap the contents of two registers, there's a simple bit-twiddling trick:
XOR R1,R2
XOR R2,R1
XOR R1,R2
This will exchange the contents of the two registers without using any memory.
I have an input port from_LS(511:0). This is declared as wire in my module. I am assigning this to a set of 32 registers ilb(0:31), each of which are 1 nits long. I was trying to use the for loop to do this.
integer i;
genvar j;
initial
begin
count1 = 0;
count2=0;
flush_ctrl=0;
buffer_bit=0;
a=(hmic_ctrl[1]) + (hmic_ctrl[2]*2) + (hmic_ctrl[3]*4);
//assigning data from LS to ilb
for (i=0;i<=31;i=i+1)
ilb[i]=from_LS[511-(16*i) : 511-(16*(i-1))];
ilb[0]= from_LS[511:496];
ilb[1]= from_LS[495:480];
ilb[2]= from_LS[479:464];
ilb[3]= from_LS[463:448];
ilb[4]= from_LS[447:432];
ilb[5]= from_LS[431:416];
ilb[6]= from_LS[415:400];
ilb[7]= from_LS[399:384];
ilb[8]= from_LS[383:368];
ilb[9]= from_LS[367:352];
ilb[10]= from_LS[351:336];
ilb[11]= from_LS[335:320];
ilb[12]= from_LS[319:304];
ilb[13]= from_LS[303:288];
ilb[14]= from_LS[287:272];
ilb[15]= from_LS[271:256];
ilb[16]= from_LS[255:240];
ilb[17]= from_LS[239:224];
ilb[18]= from_LS[223:208];
ilb[19]= from_LS[207:192];
ilb[20]= from_LS[191:176];
ilb[21]= from_LS[175:160];
ilb[22]= from_LS[159:144];
ilb[23]= from_LS[143:128];
ilb[24]= from_LS[127:112];
ilb[25]= from_LS[111:96];
ilb[26]= from_LS[95:80];
ilb[27]= from_LS[79:64];
ilb[28]= from_LS[63:48];
ilb[29]= from_LS[47:32];
ilb[30]= from_LS[31:16];
ilb[31]= from_LS[15:0];
pctr(
.clk(clk),
.reset(0),
.offset(branch_ctrl[13:1]),
.mux_select(branch_ctrl[0]),
.pc1(pc)
);
end
I was getting the error that I should not use a variable index. The error is :
# ** Error: C:/Modeltech_pe_edu_10.0/examples/COMP ARC/inst_line_buf.v(55): Range must be bounded by constant expressions.
So i wrote down the following:
ilb[0]= from_LS[511:496];
ilb[1]= from_LS[495:480];
ilb[2]= from_LS[479:464];
....
ilb[31]= from_LS[15:0];
But i guess there must be a better way to do this. Could anyone tell me how?
The orginal verilog doesnt allow this kind of expression as it wanted to assure that the width is always right (it is, but in earlier times compilers werent as good :-).
Verilog 2001 offers some solution with +: you can specify the width
e.g. from_LS[ 511-(16*i) +:16 ] in your loop.
EDIT: Another solution would be to put another loop inside, which copies 16 bits bit by bit.
You should include more code (at least up to the always block containing that loop for the sensitivity list) and the exact error you're getting.
Does it work if you change integer i to genvar i and wrap the for in generate and endgenerate?