I’ve been recently working on an AM modulation module written in VHDL, and I have made this reference model in Simulink to set the parameters of the fixed-point model based on comparing it with the output of the floating-point model.
AM modulation output
yellow:fixed-point,blude:floating-point
reference model for floating-point and fixed-point
here is the code I’ve written in VHDL:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Top_Module is
Port (
Clock : in STD_LOGIC;
Output_Signal : out signed (9 downto 0)
);
end Top_Module;
architecture Behavioral of Top_Module is
constant Coefficient : signed (7 downto 0) := to_signed(26,8);
signal DDS_Sin_430KHz : std_logic_vector (15 downto 0) := (others=>'0');
signal DDS_Cos_94Hz : std_logic_vector (7 downto 0) := (others=>'0');
signal Product_94Hz : signed (15 downto 0) := (others=>'0');
signal Product_430KHz : signed (24 downto 0) := (others=>'0');
signal Product_94Hz_Plus_One : signed (8 downto 0) := (others=>'0');
signal Output_Signal_Int : signed (9 downto 0) := (others=>'0');
COMPONENT Cos_94Hz
PORT (
aclk : IN STD_LOGIC;
m_axis_data_tvalid : OUT STD_LOGIC;
m_axis_data_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
COMPONENT Sin_430KHz
PORT (
aclk : IN STD_LOGIC;
m_axis_data_tvalid : OUT STD_LOGIC;
m_axis_data_tdata : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)
);
END COMPONENT;
begin
Cos_94Hz_Inst : Cos_94Hz
PORT MAP (
aclk => Clock,
m_axis_data_tvalid => open,
m_axis_data_tdata => DDS_Cos_94Hz
);
Sin_430KHz_Inst : Sin_430KHz
PORT MAP (
aclk => Clock,
m_axis_data_tvalid => open,
m_axis_data_tdata => DDS_Sin_430KHz
);
Output_Signal <= Output_Signal_Int;
process(Clock)
begin
if rising_edge(Clock) then
Product_94Hz <= Coefficient * signed(DDS_Cos_94Hz);
Product_94Hz_Plus_One <= Product_94Hz(14 downto 6) + to_signed(128,9);
Product_430KHz <= Product_94Hz_Plus_One * signed(DDS_Sin_430KHz);
Output_Signal_Int <= Product_430KHz(18 downto 9);
end if;
end process;
end Behavioral;
and this is for the testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_TEXTIO.all;
use std.textio.all;
entity AM_Modulation_tb is
-- Port ( );
end AM_Modulation_tb;
architecture Behavioral of AM_Modulation_tb is
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT AM_Modulation
PORT(
Clock : in STD_LOGIC;
Output_Signal : out signed (9 downto 0)
);
END COMPONENT;
-- Inputs
signal Clock : std_logic := '0';
-- Outputs
signal Output_Signal : signed(9 downto 0);
-- Clock period definitions
constant Clock_period : time := 10ns;
begin
-- Instantiate the Unit Under Test (UUT)
uut: AM_Modulation PORT MAP (
Clock => Clock,
Output_Signal => Output_Signal
);
-- Clock process definitions
Clock_process :process
begin
Clock <= '0';
wait for Clock_period/2;
Clock <= '1';
wait for Clock_period/2;
end process;
write_Output_Vector: process(Clock)
file Output_text : text open write_mode is "DesktopNew_folderAM_ModulationAM_Modulation_HDLOutput_Vec_HDL.txt";
variable LO1 : line;
begin
if rising_edge(Clock) then
write(LO1, to_integer(Output_Signal));
writeline(output_text, LO1);
end if;
end process;
end Behavioral;
but I’m having two troubles with the testbench part:
first problem is the simulation runs with an undefined clock and I have to use force clock option to give it a value(period:10ns)
and the second one is that the signal output is not correct as it’s in a simple Sinusoide form.
I’ve changed the clock entry in the middle of the simulation that’s why its frequency has been changed
I’ve also written this project in Verilog and actually I got the correct output:
`timescale 1ns / 1ps
module Top_Module (
input wire Clock,
output reg [9:0] Output_Signal
);
localparam signed [7:0] Coefficient = 8'sd32;
reg [15:0] DDS_Sin_430KHz = 16'b0;
reg [7:0] DDS_Cos_94Hz = 8'b0;
reg signed [15:0] Product_94Hz = 16'sb0;
reg signed [24:0] Product_430KHz = 25'sb0;
reg signed [8:0] Product_94Hz_Plus_One = 9'sb0;
reg signed [9:0] Output_Signal_Int = 10'sb0;
// Instantiate Cos_94Hz
Cos_94Hz Cos_94Hz_Inst (
.aclk(Clock),
.m_axis_data_tvalid(), // open
.m_axis_data_tdata(DDS_Cos_94Hz)
);
// Instantiate Sin_430KHz
Sin_430KHz Sin_430KHz_Inst (
.aclk(Clock),
.m_axis_data_tvalid(), // open
.m_axis_data_tdata(DDS_Sin_430KHz)
);
always @(posedge Clock) begin
Product_94Hz <= Coefficient * $signed(DDS_Cos_94Hz);
Product_94Hz_Plus_One <= Product_94Hz[14:6] + 9'sd128;
Product_430KHz <= Product_94Hz_Plus_One * $signed(DDS_Sin_430KHz);
Output_Signal_Int <= Product_430KHz[18:9];
Output_Signal <= Output_Signal_Int;
end
endmodule
and testbench :
`timescale 1ns / 1ps
module modulation_tb;
// Inputs
reg Clock = 0;
// Outputs
wire signed [9:0] Output_Signal;
// Clock period definitions
parameter Clock_period = 10;
// Instantiate the Unit Under Test (UUT)
AM_Modulation uut (
.Clock(Clock),
.Output_Signal(Output_Signal)
);
// Clock process definitions
always begin
# (Clock_period / 2) Clock = ~Clock;
end
// Write output vector to a file
integer file;
initial begin
file = $fopen("F:/A.R.M1111/Uni/advanced_logic_circuits/AM_Modulation_HDL/Output_Vec_HDL.txt", "w");
if (file == 0) begin
$display("Failed to open file.");
$finish;
end
end
// Write output signal to file at every clock edge
always @(posedge Clock) begin
$fwrite(file, "%dn", Output_Signal);
end
initial begin
// Run the simulation for a certain period
#500000000 $fclose(file);
$finish;
end
endmodule
and here is the output:
Any help with the VHDL one would be appreciated.