I have a number of 32 bit. I need only its first 8 bits. I think I can do this by two methods: one is by shifting the number to 24 bits right and other is by simply assigning the last 8 bits to a variable.
Here is what I am trying to do:
module Data_shiftin(
input reset_n, clk,
input [31:0] data_in,
output [31:0] data_out
);
reg [31:0] data_reg;
reg data_out;
always # (posedge clk)
begin
data_out<=data_in[31:23];
end
endmodule
But I am getting only last bit i.e. 32nd bit of the number. I don't know where I am doing error.
Thanks!
P.S: I am a newbie to this language.
The assignment you have is correct, but you are only getting one bit because you are redeclaring data_out as a single-bit reg. Try changing:
reg data_out
To:
reg[31:0] data_out
A better option though it to use Verilog-2000 style port declarations and place the reg keyword in the port list.
Example:
module Data_shiftin(
input wire reset_n,
input wire clk,
input wire [31:0] data_in,
output reg [31:0] data_out
);
always # (posedge clk)
begin
data_out <= data_in[31:23];
end
endmodule
Note also that your tool may warn you about a width mismatch because you are assigning an 8-bit value to a 32-bit value. To explicitly assign only the lower 8 bits of data_out you should use:
data_out[7:0] <= data_in[31:23]
Related
I am working with RAM in Verilog, and I need to implement a test bench where I will confirm the correct operation of the three memory processes (write data, read data and read commands). I have written a testbench where it seems to be writing and reading some integer numbers, but is there any way to fill the memory with words or strings to be more clear randomly?
This is my testbench:
module ramtest();
parameter WORD_SIZE=8;
parameter ADDR_WIDTH=8;
parameter RAM_SIZE=1<<ADDR_WIDTH;
reg we;
reg re;
reg [ADDR_WIDTH-1:0] addr;
reg [ADDR_WIDTH-1:0] instraddr;
reg [WORD_SIZE-1:0] datawr;
reg Clk;
reg [WORD_SIZE-1:0] mem[RAM_SIZE-1:0];
wire [WORD_SIZE-1:0] datard;
wire [WORD_SIZE-1:0] instrrd;
MCPU_RAMController raminst (.we(we),.datawr(datawr),.re(re),.addr(addr),.datard(datard),.instraddr(instraddr),.instrrd(instrrd));
integer i;
initial begin
we=0;
datawr=0;
instraddr=0;
addr=1;
#20;
for(i=0;i<RAM_SIZE;i=i+1) begin
datawr=i;
addr=i-1;
#10;
end
we=0;
addr=1;
instraddr=0;
for(i=0;i<RAM_SIZE;i=i+1) begin
addr=i-1;
#10;
end
end
endmodule
And here is the RAM controller code where I need to test:
module MCPU_RAMController(we, datawr, re, addr, datard, instraddr, instrrd);
parameter WORD_SIZE=8;
parameter ADDR_WIDTH=8;
parameter RAM_SIZE=1<<ADDR_WIDTH;
input we, re;
input [WORD_SIZE-1:0] datawr;
input [ADDR_WIDTH-1:0] addr;
input [ADDR_WIDTH-1:0] instraddr;
output [WORD_SIZE-1:0] datard;
output [WORD_SIZE-1:0] instrrd;
reg [WORD_SIZE-1:0] mem[RAM_SIZE-1:0];
reg [WORD_SIZE-1:0] datard;
reg [WORD_SIZE-1:0] instrrd;
always # (addr or we or re or datawr)
begin
if(we)begin
mem[addr]=datawr;
end
if(re) begin
datard=mem[addr];
end
end
always # (instraddr)
begin
instrrd=mem[instraddr];
end
endmodule
Currently, you are filling the memory with incrementing values (0, 1, 2, etc.) at incrementing addresses. One way to fill the memory with random data values is to use the $random system function.
In the testbench, change:
datawr=i;
to:
datawr=$random;
See also IEEE Std 1800-2017, section 18.13 Random number system functions and methods for more modern random functions ($urandom, etc.).
I am learning CPU Design and basic Verilog HDL. I have a processor running in tkgate on Fedora 29 and I have designed a hardware RAM disk. I can't test the RAM but have decided to replace it with an HDL RAM disk. Whenever I try to simulate the circuit, I get the error:
RAM_HDL, line 17: Illegal use of 'w7' in left-hand-side assignment.
Here is my code for the RAM:
module RAM_HDL(RAM, Data_In, Data_Out, Address, RW);
reg [15:0] RAM [127:0];
wire [15:0] Data_In;
wire [15:0] Data_Out;
wire [7:0] Address;
wire RW;
initial
$readmemb("RAM_DATA.BIN", RAM);
always #(*)
begin
if (RW)
RAM[Address] <= Data_In;
Data_Out <= Address;
end
endmodule
The error is on line 17:
Data_Out <= Address;
I believe one of your problems is trying to assign to a wire type in an always block. Try changing the declaration of Data_Out to reg instead of wire. The 2 following examples compiled for me:
module RAM_HDL(Data_In, Data_Out, Address, RW);
reg [15:0] RAM [127:0];
input wire [15:0] Data_In;
output reg [15:0] Data_Out;
input wire [7:0] Address;
input wire RW;
initial
$readmemb("RAM_DATA.BIN", RAM);
always #(*)
begin
if (RW)
RAM[Address] <= Data_In;
Data_Out <= Address;
end
endmodule
note the changes. input and output are declared on the ports. The ram array is not one of the ports and the data_out is a reg.
another option would be to move the assignment of data out outside the always block and keep it as a wire:
module RAM_HDL(Data_In, Data_Out, Address, RW);
reg [15:0] RAM [127:0];
input wire [15:0] Data_In;
output wire [15:0] Data_Out;
input wire [7:0] Address;
input wire RW;
initial
$readmemb("RAM_DATA.BIN", RAM);
always #(*)
begin
if (RW)
RAM[Address] <= Data_In;
end
assign Data_Out = Address;
endmodule
the changes are mostly the same. the input output declarations and the ram array is removed from the port list. Data_Out however is now assigned outside the always block so it can stay a wire.
The following code compiles at least:
module RAM_HDL(Data_In, Data_Out, Address, RW);
reg [15:0] RAM [127:0];
input [15:0] Data_In;
output [15:0] Data_Out;
input [7:0] Address;
input RW;
initial
$readmemb("RAM_DATA.BIN", RAM);
always #(*)
begin
if (RW)
RAM[Address] <= Data_In;
end
assign Data_Out = RAM[Address];
endmodule
module tb_alu32();
reg clk, reset;
reg [31:0] tb_a, tb_b, tb_yexpected;
reg [2:0] tb_op;
wire [31:0] tb_result;
reg[31:0] vectornum, errors;
reg[99:0] testvectors[10000:0];
...
always
begin
clk=0;#5;clk=1;#5;
end
$readmemh("C:/altera/13.0/practice/week3/alu32/testvect.tv",testvectors);
always # (posedge clk)
begin
#1; {tb_a,tb_b,tb_op,tb_yexpected} = testvectors[vectornum];
end
endmodule
I read testvect.tv but tb_a and tb_b's MSB are missing and LSB is set 0 like
0000_0001->0000_0002
0000_0002->0000_0004
FFFF_FFFF->FFFF_FFFE
FFFF_FFFE->FFFF_FFFC
8000_0001->0000_0002
How can I solve this?
If I use readmemb, it works well.
If I assign values it works well.
Why did it happen?
This is what is causing the error
Your {tb_a,tb_b,tb_op,tb_yexpected} = testvectors[vectornum];
LHS is 99 bits and RHS is 100 bits. Just declare
reg[98:0] testvectors[10000:0];
i.e instead of 100 bits, declare testvectors to be 99 bits.
I just started to work with CRC32.So when I wanted to check the code I wrote and I get xxxxxx as the output.I am not sure if the code is right though
module last_time(input [127:0]finalinput,output [31:0]crcout1
,input clk);
wire [31:0]poly;
assign poly=32'h04c11db7;
reg [7:0]lsb;
reg [3:0]i;
reg [7:0]ans;
reg [31:0]nextcrc;
reg [31:0]newcrc;
reg [31:0]crcout;
reg [7:0] lut [255:0];
always#(posedge clk)
begin
crcout=32'hffffffff;
lsb=finalinput;
for(i=0;i<16;i=i+1)
begin
ans=(8'hff^(lsb));
newcrc = lut[ans];
$readmemh("table.txt",lut); // to fill lut
nextcrc=(newcrc)^(crcout>>8);
lsb=lsb>>8;
end
end
assign crcout1=nextcrc^32'hffffffff;
endmodule
The issue was with the input to the LUT, it should be an integer and not a reg value.
The LUT size was not the correct size
module bit32(input [31:0]msg,input [31:0]crcinitial,output reg[31:0]tableout,output [23:0]crcshifted,
output[31:0]newcrc,output reg [7:0]xor1);
wire [7:0]msglsb;
assign msglsb=msg;
wire [7:0]crclsb;
assign crclsb=crcinitial;
integer k;
reg [31:0]lut[0:255];
initial
begin
assign xor1=(crclsb^msglsb)&8'hff;
assign k=xor1;
assign tableout=lut[xor1];
$readmemh("table.txt",lut);
end
assign crcshifted=crcinitial>>8;
assign newcrc=(tableout^crcshifted)^32'hffffffff;
endmodule
In my previous question I said that I was asked to design a bottling system that fills bottles with the desired number of tablets. In part1 of my project, the user will press the button on FPGA to identify how many tablets will be put in the each bottle and the desired number will be displayed.This is the code of part 1 I have written for my project and I have no idea why it is giving errors in module part1.
module count(clk,clr,cntEn,dout);
input clk,clr,cntEn;
output reg [8:0] dout ;
always#(posedge clk)
begin
if(clr)
dout<=0;
else if(cntEn)
dout<=dout+1;
end
endmodule
module sevenseg(num,dout);
input [3:0] num;
output reg [6:0] dout;
always#(*) begin
case(num)
0:dout=7'b1111110;
1:dout=7'b1100000;
2:dout=7'b1011011;
3:dout=7'b1001111;
4:dout=7'b1100110;
5:dout=7'b1101101;
6:dout=7'b1111101;
7:dout=7'b0000111;
8:dout=7'b1111111;
9:dout=7'b1101111;
endcase
end
endmodule
module part1(clk,clr,cntEn,dout);
input clk, clr, cntEn;
output dout;
wire w1;
begin
count count_1 (clk, clr, cntEn, w1);
sevenseg sevenseg_1(w1, dout );
end
endmodule
The error was pointed out byljk07, the begin end in module 1 are not required, some parsers might just ignore them others will throw an error. it should be:
module part1(clk,clr,cntEn,dout);
input clk, clr, cntEn;
output dout;
wire w1;
count count_1 (clk, clr, cntEn, w1);
sevenseg sevenseg_1(w1, dout );
endmodule
I think it is also worth pointing out that unless your constrained to Verilog-95 then adopting an ANSI style port declaration is preferred, as it lead to easier to maintain code.
module part1(
input clk, clr, cntEn,
output dout
);
wire w1;
count count_1 (clk, clr, cntEn, w1);
sevenseg sevenseg_1(w1, dout );
endmodule
Module sevenseg also has an incomplete case statement which will lead to implied latches. either add a default or fully specify the output for all options of num:
module sevenseg(num,dout);
input [3:0] num;
output reg [6:0] dout;
always #(*) begin
case(num)
0:dout=7'b1111110;
1:dout=7'b1100000;
2:dout=7'b1011011;
3:dout=7'b1001111;
4:dout=7'b1100110;
5:dout=7'b1101101;
6:dout=7'b1111101;
7:dout=7'b0000111;
8:dout=7'b1111111;
9:dout=7'b1101111;
default: dout='b0;
endcase
end
endmodule