Hi,
I'm trying to do multiply-and-accumulate (MAC) in a custom IP created
by Create/Import IP peripherals in XPS. Xilinx provides basic
read/write functions with the user_logic vhdl code. I removed the code
for reg2 and reg3 in these two processes. I then added MUL_AND_ACCUM
process. I'm not a vhdl programmer, so I'm having difficulty with this
simple piece of logic. All I'm trying to do is
mul (reg3) = num1 (reg0) * num2 (reg1);
accum (reg2) = accum (reg2) + mul (reg3);
I wrote a process:
MUL_AND_ACCUM_PROC : process( Bus2IP_Clk) is
begin
if Bus2IP_Clk'event and Bus2IP_Clk = '1' then
if Bus2IP_Reset = '1' then
slv_reg2 <= (others => '0');
slv_reg3 <= (others => '0');
else
if slv_reg_write_select = "0010" then
slv_reg2 <= Bus2IP_Data(0 to 31);
else
slv_reg3 <= slv_reg0 * slv_Reg1;
slv_reg2 <= slv_reg2 + slv_reg3;
end if;
end if;
end if;
end process MUL_AND_ACCUM_PROC;
I suppose when I write a 0 to slv_reg2, it'll initialize slv_reg2 to 0.
Once it's initialized, I can simply write to slv_reg0 and slv_reg1, and
obtain the accumulated value in slv_reg2. But when I wrote a test
program in C to test this IP:
FPGA_MAC_mWriteReg(XPAR_FPGA_MAC_0_BASEADDR,0x8,3);
FPGA_MAC_mWriteReg(XPAR_FPGA_MAC_0_BASEADDR,0,8);
a = FPGA_MAC_mReadReg(XPAR_FPGA_MAC_0_BASEADDR,0);
printf("a: %d\n",a);
FPGA_MAC_mWriteReg(XPAR_FPGA_MAC_0_BASEADDR,0x4,4);
b = FPGA_MAC_mReadReg(XPAR_FPGA_MAC_0_BASEADDR,0x4);
printf("b: %d\n",b);
product = FPGA_MAC_mReadReg(XPAR_FPGA_MAC_0_BASEADDR,0xc);
printf("product = : %d\n",product);
output = FPGA_MAC_mReadReg(XPAR_FPGA_MAC_0_BASEADDR,0x8);
printf("output = : %d\n",output);
I have the following output:
a: 8
b: 4
product = : 1657088
output = : 32
a: 2
b: 5
product = : 12544852
output = : 10
It seems product and output are reversed somehow. It just doesn't work
as I expected. I can't figure out what's wrong with my code. I have
very little knowledge of vhdl. Can anyone point it out to me? The
following shows the read/write processes. Thanks.
SLAVE_REG_WRITE_PROC : process( Bus2IP_Clk ) is
begin
if Bus2IP_Clk'event and Bus2IP_Clk = '1' then
if Bus2IP_Reset = '1' then
slv_reg0 <= (others => '0');
slv_reg1 <= (others => '0');
else
case slv_reg_write_select is
when "1000" => slv_reg0 <= Bus2IP_Data(0 to 31);
when "0100" => slv_reg1 <= Bus2IP_Data(0 to 31);
when others => null;
end case;
end if;
end if;
end process SLAVE_REG_WRITE_PROC;
-- implement slave model register read mux
SLAVE_REG_READ_PROC : process( slv_reg_read_select, slv_reg0,
slv_reg1, slv_reg2, slv_reg3 ) is
begin
case slv_reg_read_select is
when "1000" => slv_ip2bus_data <= slv_reg0;
when "0100" => slv_ip2bus_data <= slv_reg1;
when "0010" => slv_ip2bus_data <= slv_reg2;
when "0001" => slv_ip2bus_data <= slv_reg3;
when others => slv_ip2bus_data <= (others => '0');
end case;
end process SLAVE_REG_READ_PROC;