keyboardcowboy
Member level 3
- Joined
- Mar 4, 2010
- Messages
- 55
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 1,286
- Activity points
- 1,715
reg [1023:0] wk;
bitsleft=0;
if(pushin) begin // pushin is just a variable which is set to 1 when i want to insert data
for(ix=bitsleft; ix < bitsleft+32; ix=ix+1)
wk[ix]=datain[ix-bitsleft]; // datain is the 32bit that i am pushing in, random.
bitsleft += 32;
expdata=wk[14:0];
expdata &= ~(16'hffff << reqlen); //reqlen is the length of the bits to be extracted, random from 0 to 15
bitsleft -= reqlen;
wk = wk >> reqlen;
It depends, if they are serially clocked out of a shift register or copied bit-shifted in one cycle.
Like ads-ee I presume that you want to write synthesizable code, but you didn't mention it explicitely.
This eases implementation. You can e.g. split the design into to a FIFO with 32 bit input width/1 bit output width and a shift register that assembles the output bits to a word of the intended variable width.they are serially clocked out
Current generation parts and tools only allow a 8-to-1 width reduction so x32 becomes x4. I checked this on K7 and V7 don't know about S6.You can e.g. split the design into to a FIFO with 32 bit input width/1 bit output width
Never considered it to be all that tricky, been doing it for years on many designs. Serializing the input works well if you don't have bursting data. For bursting input data with a contiuous serial output it has to be done at the output.It's a bit tricky because you must potentially assemble parts of two 32 bit words.
O.K., it should be sufficient to have a 32-bit output SR that is loaded each time when the last data bit has been shifted out.
module bits(input clk, input rst, input pushin, input [31:0] datain, input reqin, input [3:0] reqlen,
output pushout, output [3:0] lenout, output [14:0] dataout);
reg [14:0] _dataout,_dataout2;
reg [3:0] request[31:0];
reg [31:0] fifo[31:0];
reg [4:0] write,read,rwrite,rread;
wire [4:0] write_inc = write + 1;
reg _pushout;
reg _lenout;
reg shiftop;
reg [31:0] data;
reg [4:0] shift_counter,shift_counter2;
reg load;
reg [4:0] totalrequests;
reg firstrun;
assign pushout = _pushout;
assign lenout = _lenout;
assign empty = (write == read);
assign full = (write_inc == read);
assign dout = fifo[read];
always @(posedge clk) begin
_pushout <= #1 0;
_lenout <=#1 0;
if (shiftop) begin // shifter code
if(request[rread] != 0) begin // this checks if a request for 0 bits was made, is it was made then 0 is the output
if(load) begin // if the request was not zero and the load flag is set
data <= fifo[read]; // load data from fifo, invert the load flag
load <= 0;
end else if (shift_counter != request[rread]) begin //check if amount of shift performed by shifter is less then requested length
data <= {0,data[31:1]}; //shifter logic
_dataout <= {data[0],_dataout2}; //shifter logic
shift_counter <= shift_counter + 1; //two counters are used, one is for the required shift, and the other indicates if 32 bits have been shifted in which case another value is loaded from fifo
shift_counter2 <= shift_counter2 +1;
end else begin
rread<= rread+1;
totalrequests<= totalrequests -1;
end
if (shift_counter2 == 31) begin
read <= read + 1;
load <= ~load;
end
if (totalrequests ==0) begin
shiftop <= ~ shiftop;
end
end else begin
firstrun<=#1 0;
_lenout<= 0;
_pushout <= 0;
rread <= rread +1;
end
end
end
always @(posedge clk) begin
if (rst) begin
write <= #1 0;
read <= #1 0;
rwrite <= #1 0;
rread <= #1 0;
shiftop <= #1 0;
load <= #1 0;
firstrun <= #1 0;
totalrequests <= #1 0;
shift_counter <= #1 0;
shift_counter2 <= #1 0;
_dataout <= #1 0;
end
if (pushin) begin //If a new value is pushed in
fifo[write] <= #1 datain; //value "datain" goes into fifo
write <= #1 write_inc; //write pointer is incremented
end
if (reqin && (!empty)) begin //if a request for bits arrive, the requests are stored inside a seperate fifo becasue multiple requests come at the same time.
request[rwrite] <=#1 reqlen; //seperate write pointer of requests fifo is incremented
rwrite <= #1 rwrite + 1;
totalrequests<= totalrequests+1; //variable totalrequests is incremented, this contains the total requests made.
if (firstrun == 0) begin //firstrun flag indicates that the shifter is being run for the first time
load <=#1 1; //load flag is raised which causes the shiter to load data from fifo
shiftop <= #1 1;
end else begin
load <= #1 0;
shiftop <= #1 0;
end
end
end
endmodule
`timescale 1ns/10ps
module test;
reg clk,rst,pushin;
reg [31:0] datain;
reg reqin;
reg [3:0] reqlen;
wire pushout;
wire [3:0] lenout;
wire [14:0] dataout;
reg pushout0;
reg [3:0] lenout0;
reg [14:0] dataout0;
reg draining;
reg filling;
int bitsleft;
reg running=0;
reg debug=0;
default clocking tclk @(posedge(clk)) ;
endclocking
typedef struct {
reg[3:0] len;
reg[14:0] data;
} sexp;
sexp fexp[$];
sexp exp;
task death(input string s);
begin
$display();
$display();
$display(s);
$display();
$display();
$error(":-( :-( :-( ended with error");
$display();
$display();
$finish;
end
endtask
class rt;
rand reg Xpushin;
rand reg [31:0] Xdatain;
rand reg Xreqin;
rand reg [3:0] Xreqlen;
rand reg [8:0] Xdrain;
rand reg [8:0] Xfill;
reg [14:0] expdata;
reg [31*32-1:0] wk;
constraint c1 {
Xpushin dist {
0 := 20-19*filling,
1 := 3
};
}
constraint c2 {
Xreqlen <= bitsleft;
}
function new();
begin
bitsleft=0;
wk=0;
draining=0;
filling=0;
end
endfunction
task apply;
integer ix;
sexp se;
begin
if( bitsleft > (30*32-1) ) begin
Xpushin=0;
end
if(bitsleft < Xreqlen) begin
Xreqin=0;
end
if(filling) begin
if(bitsleft < 29*32) Xreqin=0; else filling=0;
end else if(draining) begin
if(bitsleft > 0) Xpushin=0;
if(bitsleft == 0) draining=0;
end else begin
if( Xdrain == 123 ) draining=1;
else if(Xfill == 123) filling=1;
end
##1 #1;
pushin = Xpushin;
datain = Xdatain;
reqin = Xreqin;
reqlen = Xreqlen;
if(Xpushin) begin
for(ix=bitsleft; ix < bitsleft+32; ix=ix+1) wk[ix]=Xdatain[ix-bitsleft];
// wk[bitsleft+31:bitsleft]=Xdatain;
bitsleft += 32;
if(debug) $display("Pushing %08h",Xdatain);
end
if(Xreqin) begin
expdata=wk[14:0];
expdata &= ~(16'hffff << Xreqlen);
se.len = Xreqlen;
se.data=expdata;
if(debug) $display("requesting %d bits, expecting %04h",Xreqlen,expdata);
fexp.push_back(se);
bitsleft -= Xreqlen;
wk = wk >> Xreqlen;
end
end
endtask
task alldone;
begin
if(fexp.size() > 0) begin
death("You did not push out the last request within 20 clocks");
$finish;
end
end
endtask
endclass
rt t=new();
bits b(clk,rst,pushin, datain, reqin, reqlen, pushout, lenout, dataout);
initial begin
clk=0;
forever #5.0 clk=~clk;
end
initial begin
#1;
if(debug) begin
$dumpfile("bits.vcd");
$dumpvars(9,test);
end
end
initial begin
rst=0;
pushin=0;
datain=0;
reqin=0;
reqlen=0;
##1 #1;
rst=1;
##5 #1;
rst=0;
##1 ;
running=1;
repeat(100) begin
t.randomize;
t.apply;
end
##1 #1;
pushin=0;
reqin=0;
##20 #1;
t.alldone;
$display();
$display();
$display("all done with a smile");
$display();
$display();
$finish();
end
always @(posedge(clk)) begin
if(running) begin
pushout0=pushout;
lenout0=lenout;
dataout0=dataout;
#0.02;
if(pushout0 !== pushout) death("No hold time on pushout");
if(lenout0 !== lenout) death("No hold time on lenout");
if(dataout0 !== dataout) death("no hold time on dataout");
if(pushout !== 0 && pushout !==1) death("X or Z on pushout");
if(pushout) begin
if(fexp.size() < 1) death("You pushed, and I am not expecting anything");
exp = fexp.pop_front();
if(lenout !== exp.len) begin
$display();
$display();
$display("Length error --- Recv %h Exp %h",lenout,exp.len);
death("length received in error");
end
if(dataout !== exp.data) begin
$display();
$display();
$display("Data error --- Recv %h Exp %h",dataout,exp.data);
death("Data received error");
end
end
end
end
endmodule
module bits(input clk, input rst, input pushin, input [31:0] datain, input reqin, input [3:0] reqlen,
output pushout, output [3:0] lenout, output [14:0] dataout);
reg [5:0] totalrequests;
reg [3:0] _lenout;
reg _pushout;
reg [31:0] fifo[31:0];
reg [3:0] lenfifo[95:0];
reg [4:0] write,read;
reg [5:0] lread,lwrite;
wire [4:0] write_inc = write + 1;
wire [5:0] lwrite_inc = lwrite + 1;
reg firstrun;
reg [31:0] temp;
reg [14:0] sout,shftout;
reg load;
reg [3:0] count1;
reg [4:0] count2;
reg enable,enable2;
reg shiftenable;
reg [14:0] _dataout;
reg [14:0] souttemp;
integer ii;
reg[3:0] wi;
reg once;
assign dataout = _dataout;
assign pushout = _pushout;
assign lenout = _lenout;
assign empty = (write == read);
assign full = (write_inc == read);
assign dout = fifo[read];
always @(posedge clk) begin
//_pushout <= #1 0;
//_lenout <=#1 0;
if(shiftenable) begin
if(lenfifo[lread] != 0) begin
if(load)begin
temp <= #1 fifo[read];
load <= #1 0;
enable <= #1 1;
end else if(enable) begin
temp <= #1 {0,temp[31:1]};
count1 <= #1 count1 +1;
count2 <= #1 count2 +1;
sout <= #1 {sout,temp[0]};
if (count1 == lenfifo[lread]) begin
for (ii=0; ii <= 14; ii=ii+1) souttemp[ii]=sout[wi-ii];
_dataout <= #1 souttemp;
if(lenfifo[lread] < 14) begin
_dataout <= #1 souttemp >> (14-lenfifo[lread]);
end
_lenout <= #1 count1;
_pushout <=#1 1;
//enable <= #1 0;
totalrequests <= totalrequests -1;
lread <= lread +1;
count1 <= #1 0;
sout<= #1 0;
if (totalrequests == 0) begin
shiftenable <= 0;
end
end else _pushout <= #1 0;
end
if (count2 == 31) begin
load <= #1 1;
end
end else if(lenfifo[lread] != 0) begin
lread <= #1 lread +1;
_pushout <= #1 1;
_lenout <= #1 0;
_dataout <= #1 0;
end else _pushout <= #1 0;
end
end
always @(posedge clk) begin
if (rst) begin
once <= #1 1;
shftout <= #1 0;
write <= #1 0;
read <= #1 0;
lwrite <= #1 0;
lread <= #1 0;
load <= #1 0;
count1 <= #1 0;
count2 <= #1 0;
firstrun <= #1 1;
enable2 <= #1 1;
totalrequests <= #1 0;
_pushout <= #1 0;
wi <= #1 14;
end
if (pushin) begin
fifo[write] <= #1 datain;
write <= #1 write_inc;
end
if (reqin== 1 && empty==1) begin
_pushout <= #1 1;
_lenout <= #1 0;
_dataout <= #1 0;
end else if(firstrun) _pushout <= #1 0;
if (reqin && !(empty)) begin
//if(reqlen != 0) begin
lenfifo[lwrite] <= #1 reqlen;
lwrite <= #1 lwrite_inc;
totalrequests <= #1 totalrequests +1;
if (firstrun) begin
load <= #1 1;
shiftenable <= #1 1;
firstrun <=#1 0;
end
//read <= read + 1;
//end
end
end
endmodule
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?