Reputation: 13
I'd like to make an output bus 1 bit shorter than the input, by cutting a bit from arbitrary position, like this:
module jdoodle;
integer i;
reg [8:0] in;
reg [7:0] out;
reg [3:0] idx;
always @*
begin
case(idx)
0: out = in[8:1];
1: out = {in[8:2], in[0]};
2: out = {in[8:3], in[1:0]};
3: out = {in[8:4], in[2:0]};
4: out = {in[8:5], in[3:0]};
5: out = {in[8:6], in[4:0]};
6: out = {in[8:7], in[5:0]};
7: out = {in[8], in[6:0]};
default: out = in[7:0];
endcase
end
initial begin
in = 9'b010101010;
for (i = 0; i < 9; i++)
begin
idx = i; #10;
$display ("%x - %08b", idx, out);
end
$finish;
end
endmodule
I found a way to write it in one line:
module jdoodle;
integer i;
reg [8:0] in;
reg [3:0] idx;
wire [7:0] out;
assign out = ((in >> 1) & (16'h00ff << idx)) | (in & (16'hff00 >> (16-idx)));
initial begin
in = 9'b010101010;
for (i = 0; i < 9; i++)
begin
idx = i; #10;
$display ("%x - %08b", idx, out);
end
$finish;
end
endmodule
But its less readable than the first, but the first is quite bad for larger buses. Is there a more elegant way to do it? Also is there standard library for verilog like std for c++, containing common modules like arbitrary rotate?
Thanks
Edit: here's the expected output:
0 - 01010101
1 - 01010100
2 - 01010110
3 - 01010010
4 - 01011010
5 - 01001010
6 - 01101010
7 - 00101010
8 - 10101010
Upvotes: 1
Views: 345
Reputation: 2685
You can use a loop to work on each bit:
module jdoodle #(parameter INW = 'd9)
(
input [INW-1:0] in,
output[INW-2:0] out,
input [$clog2(INW)-1:0] idx
);
always_comb begin
for(int i = 0; i<INW; i++) begin
if (i < idx) out[i] = in[i];
else if (i > idx) out[i-1] = in[i];
// do nothing if i == idx
end
end
endmodule
Upvotes: 1