In this assignment you will use a RAM to implement a trigonemetric LUT function. The RAM will be initialized from a data file containing values of y=255*sin(pi*x/512)
. The values of x
shall be 8-bit unsigned integers in the range 0 to 255, and the values of y
shall be rounded off to 8-bit unsigned integers in the range 0 to 255.
The 8-bit input/output values can be interpreted as unsigned integers or as fixed-point non-negative fractional values 0, 1/255, 2/255, and so on up to 255/255. Under the fixed-point interpretation, the function becomes y = sin(pi*x/2)
. The function is written differently since we changed the numerical interpretation, but the binary values are unchanged.
The LUT data can be generated using Matlab or another high-level programming language. In this exercise we will use Octave (a free clone of Matlab), and the commands should work precisely the same in Matlab.
First, use Octave/Matlab to create and verify a sample vector:
x = 0:255;
y = round(255*sin(pi*x/512));
plot(x,y)
These lines should produce a plot showing one quarter-wave of a sin function. It should rise from a minimum of 0 at x=0
up to a maximum of 255 where x=255
.
Next, you should convert the samples to hexadecimal form and save them to a data file:
fid=fopen('sin_table.dat','w'); % Open file for writing
for idx=1:256
fprintf(fid,'%02x\n',y(idx)); % Write hex data, one byte per line
end
fclose(fid); % close file
In a terminal, verify the contents of sin_table.dat
:
less sin_table.dat
You should see a column of hexadecimal bytes like this:
00
02
03
05
06
08
09
0b
0d
0e
10
11
13
14
16
17
19
1b
1c
1e
1f
Create a RAM module based on the previous assignment. Name the module sin_table
. The WIDTH
should be 8, the DEPTH
should be 256, and the ADR_WIDTH
should be 8. In the module, add an initial
assignment like this:
initial begin
$readmemh("sin_table.dat", ram, 0, 255);
end
This will initialize the ram with data from sin_table.dat
.
For this application, we do not need to mofidy the RAM contents. Comment out or delete lines pertaining to write operations. With no write operations, this RAM becomes a ROM.
We can verify the sin table in Verilog using variables of type real
and mathematical system tasks. A real
variable is not synthesizeable but is very useful to confirm signal calculations. Create an always
scope for stimulus and reporting:
reg [8:0] adr;
real sin_x, sin_y;
// Get a new random adr every clk cycle:
always @(posedge clk) begin
= $random();
adr end
// When dout changes, display it:
always @(dout) begin
= adr/255.0;
sin_x = dout/255.0;
sin_y $write("adr %3d dout %3d: sin(%1.3f)=%1.3f, should be %1.3f",adr,dout,sin_x, sin_y, $sin(3.14159*sin_x/2));
$fwrite(fid,"adr %3d dout %3d: sin(%1.3f)=%1.3f, should be %1.3f",adr,dout,sin_x, sin_y, $sin(3.14159*sin_x/2));
end
This is a simulation-only assignment, no build.
sin_table.dat
and save it in the assignment directory (not in src
).sin_table
module and testbench
.sin_table
output and the $sin()
result. This difference is due to round-off error. The first two significant figures should match.Turn in your work using git
:
git add src/*.v *.txt sin_table.dat Makefile
git commit . -m "Complete" git push origin master
Indicate on Canvas that your assignment is done.