I have to make a 8-bit ALU which is connected to a shift register. I think this is the code for a ALU but what is the best way to connect it too 8-bit shift register with a reset and clock? Im not sure how to use an internal signal to connect these two components, should they both have separate
library IEEE;
use IEEE.STD_LOGIC_1164.ALL; -- Calling libary's to be used
use IEEE.NUMERIC_STD.ALL;
entity lu is
port( Clk : in std_logic; -- The clock signal
A : in signed(7 downto 0); -- The A Input
B : in signed(7 downto 0); -- The B Input
OPCODE : in unsigned(2 downto 0); -- Op code entered into ALU
RES :in std_logic; -- The reset pin
Q : out signed(7 downto 0) -- The Output of LU
);
end lu; -- End Entity
architecture Behavioral of lu is
signal Reg1,Reg2,Reg3 : signed(7 downto 0) := (others => '0'); --The signal declaration
begin
Reg1 <= A; -- Linking Reg1 Signal to Input A
Reg2 <= B; -- Linking Reg2 Signal to Input B
Q <= Reg3; -- Linking Output Q to Signal Reg3
process(Clk)
begin
if(rising_edge(Clk)) then -- Calculate at the positive edge of clk
case OPCODE is
when "000" =>
Reg3 <= Reg1 + Reg2; -- Output is = to addition
when "001" =>
Reg3 <= Reg1 - Reg2; -- Output is = to subtraction
when "010" =>
Reg3 <= not Reg1; -- Output is = to NOT gate
when "011" =>
Reg3 <= Reg1 nand Reg2; -- Output is = to NAND gate
when "100" =>
Reg3 <= Reg1 nor Reg2; -- Output is = to NOR gate
when "101" =>
Reg3 <= Reg1 and Reg2; -- Output is = to AND gate
when "110" =>
Reg3 <= Reg1 or Reg2; -- Output is = to OR gate
when "111" =>
Reg3 <= Reg1 xor Reg2; -- Output is = to XOR gate
when others => -- If anyother Input Outputs nothing
NULL;
end case;
end if;
end process;
end Behavioral;
Assuming you mean to add logical operations to the ALU code provided, you need to make two changes:
1) In the ports list, increase the width of your opcode signal so that you can add new opcode values:
OPCODE: in unsigned(3 downto 0); -- Operation selection for the ALU
2) In your case statement, simply add the new conditions and the code to perform the logical operations:
case OPCODE is
...
when "1000" =>
Reg3 <= Reg1 srl to_integer(Reg2); -- Reg3 <= Reg1 shifted Reg2 bits to the right
when "1001" =>
Reg3 <= Reg1 sll to_integer(Reg2); -- Reg3 <= Reg1 shifted Reg2 bits to the left
when "1010" =>
Reg3 <= Reg1 ror to_integer(Reg2); -- Reg3 <= Reg1 rotated Reg2 bits to the right
when "1011" =>
Reg3 <= Reg1 rol to_integer(Reg2); -- Reg3 <= Reg1 rotated Reg2 bits to the right
when others =>
Reg3 <= (others => '0');
end case;
Related
This code works except for the add and subtract operations denoted by opcode 010 and 110 respectively. When I try to add the numbers the result looks as though a and b are being XOR'd and subtracting does A XNOR B. I have no idea why this is happening pls help. Also I am not allowed to use arithmetic plus or minus in my code the point of it is to add logically.
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.numeric_std.ALL;
ENTITY Lab3ALU IS
PORT(
opcode :IN STD_LOGIC_VECTOR(2 DOWNTO 0);--INPUT
a :IN STD_LOGIC_VECTOR(31 DOWNTO 0);--INPUT
b :IN STD_LOGIC_VECTOR(31 DOWNTO 0);--INPUT
Cout :OUT STD_LOGIC;
Zero :OUT STD_LOGIC;
q :OUT STD_LOGIC_VECTOR(31 DOWNTO 0));--OUTPUT
END Lab3ALU;
ARCHITECTURE description of Lab3ALU IS
SIGNAL Reg1, Reg2, Reg3, Result : STD_LOGIC_VECTOR(31 DOWNTO 0);
SIGNAL Cin, Sum, Carry : STD_LOGIC;
BEGIN
-- Update the register output on the clock's rising edge
process (a,b, opcode)
begin
Cin <= opcode(2);
Reg1 <= a;--temporarirly store A in Reg1 local variable
Reg2 <= b;--temporarily store B in Reg2 local variable
Reg3 <= NOT b;
case opcode is
When "000" => Result <= Reg1 AND Reg2;--AND
When "001" => Result <= Reg1 OR Reg2;--OR
When "010" =>
addloop: for i in 0 to 31 loop
Result(i) <= ((Reg1(i) XOR Reg2(i)) XOR Cin);
Cin <= (((Reg1(i) XOR Reg2(i))AND Cin)OR (Reg1(i) AND Reg2(i)));
end loop addloop;
When "110" =>
subloop: for i in 0 to 31 loop
Result(i) <= ((Reg1(i) XOR Reg3(i)) XOR Cin);
Cin <= (((Reg1(i) XOR Reg3(i))AND Cin)OR (Reg1(i) AND Reg3(i)));
end loop subloop;
When "100" => Result(31 downto 1) <= reg1(30 downto 0);
Result(0) <= '0';
Cin <= '0';
When "101" => Result(30 downto 0) <= reg1(31 downto 1);
Result(31) <= '0';
Cin <= '0';
When others => Result <= "00000000000000000000000000000000";
end case;
if Result = "00000000000000000000000000000000" then
Zero <= '1';
else
Zero <= '0';
end if;
q<= Result;
Cout<= Cin;
end process;
END description;```
I have a few questions related to this problem:
So I need to implement this in VHDL in structural mode.The given resource has to be able to do a loadX, loadY,shift and hold and change lsb to 1.(so mode should be on 3 bits-5 modes) I know that I need to use components but I'm stuck to what type of components I should use. Otherwise I would've implemented this as a shift register. Any small help would be great.I'm new to VHDL. I'd post code but as I said I'm not quite sure where to start.
If my understanding is correct, Well you can define loadX and loadY as input pins and an output port.
entity resourceB is
port (
modein : in std_logic_vector(2 downto 0);
loadX : in std_logic_vector(3 downto 0);
loadY : in std_logic_vector(3 downto 0);
loadO : out std_logic_vector(3 downto 0));
end resourceB;
since you need to perform a shift operation depending on the type of mode then I believe you need to make use of a case statement. But then since you need to change the lsb to 1, you might also need a temporary register to do it.
Architecture behave of resourceB is
signal temp_r, temp_d, temp_q : std_logic_vector(3 downto 0):= (others => '0');
begin
process(clk, reset)
begin
if(reset = '1') then
temp_q <= (others => '0');
elsif (clk'event and clk = '1') then
temp_q <= temp_d;
end if;
end process;
loadO <= temp_q;
process(modein, loadX, loadY)
begin
case modein is
when "000" => temp_d <= loadX <some shift operation> loadY;
temp_d(0) <= '1';
when "001" => temp_d <= loadX <some shift operation> loadY;
temp_d(0) <= '1';
when "010" => temp_d <= loadX <some shift operation> loadY;
temp_d(0) <= '1';
when "011" => temp_d <= loadX <some shift operation> loadY;
temp_d(0) <= '1';
when "100" => temp_d <= loadX <some shift operation> loadY;
temp_d(0) <= '1';
end case;
end process;
end behave;
" some shift operation " can be either of the shift operations which is upto you and you need to fill in that part.
NOTE: The above code might have some bugs in it, but I wrote that based on my understanding from your problem description.
I have to do UART with vhdl on the Xilinx which will send 16 chars string. I wrote such code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.ALL;
entity uartByJackob is
Port ( CLK, A, B, C : in STD_LOGIC;
RESET : in STD_LOGIC;
TxD, TxDOSC : out STD_LOGIC);
end uartByJackob;
architecture Behavioral of uartByJackob is
signal K: std_logic_vector(14 downto 0);
signal Q: std_logic_vector(3 downto 0);
signal CLK_Txd: std_logic;
signal ENABLE: std_logic;
signal QTxD: std_logic_vector(9 downto 0);
signal DATA : STD_LOGIC_VECTOR(7 downto 0);
-- freq of clock
begin
process(CLK, RESET)
begin
if rising_edge(CLK) then
if(A = '1' and K < 10416) then
K <= K + 1;
CLK_Txd <= K(13);
elsif(B = '1' and K < 5208) then
K <= K + 1;
CLK_Txd <= K(12);
elsif(C = '1' and K < 20832) then
K <= K + 1;
CLK_Txd <= K(14);
else
K <= (others => '0');
end if;
end if;
end process;
--counter
process(CLK_Txd, RESET, ENABLE)
begin
if(RESET = '1' and ENABLE = '0') then
Q <= "0000";
elsif (rising_edge(CLK_Txd)) then
Q <= Q + 1;
end if;
end process;
--comparator
ENABLE <= '1' when (Q > 4) else '0';
--transcoder
process(Q, CLK_Txd)
begin
if (rising_edge(CLK_Txd)) then
case Q is
when "0001" => DATA <= x"40";
when "0010" => DATA <= x"41";
when "0011" => DATA <= x"42";
when "0100" => DATA <= x"43";
when "0101" => DATA <= x"44";
when "0110" => DATA <= x"45";
when "0111" => DATA <= x"46";
when "1000" => DATA <= x"47";
when "1001" => DATA <= x"48";
when "1010" => DATA <= x"49";
when "1011" => DATA <= x"50";
when "1100" => DATA <= x"51";
when "1101" => DATA <= x"52";
when "1110" => DATA <= x"53";
when "1111" => DATA <= x"54";
when others => DATA <= x"55";
end case;
end if;
end process;
--uart
process(CLK_Txd, ENABLE, DATA)
begin
if(ENABLE = '0') then
QTxD <= DATA & "01";
elsif rising_edge(CLK_Txd) then
QTxD <= '1'&QTxD(9 downto 1);
end if;
end process;
TxD <= QTxD(0);
TxDOSC <= QTxD(0);
end Behavioral;
It's send data completely not connected with that what i have in transcoder and realy dont know why. Do you have any ideas what is wrong with my code, or do you have any diffrent examples of it how to send your own 16 chars with uart? I suppose that something is wrong with my counter or comparator.
--EDIT
Thans for your effort, i can't try your code at the Xilinx right now couse I am workin on it at my university. I see that you made a lot of changes in my code. Of course first i try to do it like you show and i hope this will be acceptable, but I propably have to do it with transcoder according to this picture.
From last time i made such changes i my code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.ALL;
entity uartByJackob is
Port ( CLK, A, B, C : in STD_LOGIC;
RESET : in STD_LOGIC;
TxD, TxDOSC : out STD_LOGIC);
end uartByJackob;
architecture Behavioral of uartByJackob is
signal K: std_logic_vector(14 downto 0);
signal Q: std_logic_vector(7 downto 0);
signal CLK_Txd: std_logic;
signal ENABLE: std_logic;
signal QTxD: std_logic_vector(7 downto 0);
signal DATA : STD_LOGIC_VECTOR(7 downto 0);
signal QPrim: std_logic_vector(3 downto 0);
begin
process(CLK, RESET)
begin
CLK_Txd <= CLK;
end process;
process(CLK_Txd, RESET, ENABLE)
begin
if(ENABLE = '0') then
Q <= "00000000";
elsif (rising_edge(CLK_Txd)) then
Q <= Q + 1;
end if;
end process;
ENABLE <= '1' when (Q <= 255) else '0';
process(Q(7 downto 4))
begin
case Q(7 downto 4) is
when "0000" => DATA <= x"40";
when "0001" => DATA <= x"41";
when "0010" => DATA <= x"42";
when "0011" => DATA <= x"43";
when "0100" => DATA <= x"44";
when "0101" => DATA <= x"45";
when "0110" => DATA <= x"46";
when "0111" => DATA <= x"47";
when "1000" => DATA <= x"48";
when "1001" => DATA <= x"49";
when "1010" => DATA <= x"50";
when "1011" => DATA <= x"51";
when "1100" => DATA <= x"52";
when "1101" => DATA <= x"53";
when "1110" => DATA <= x"54";
when "1111" => DATA <= x"55";
when others => DATA <= x"56";
end case;
end process;
process(CLK_Txd, ENABLE, DATA)
begin
if(ENABLE = '1') then
QTxD <= DATA;
elsif rising_edge(CLK_Txd) then
QTxD <= '1'&QTxD(7 downto 1);
end if;
end process;
TxD <= QTxD(0);
TxDOSC <= QTxD(0);
end Behavioral;
According to that i send MSB to transcoder and LSB to comparator but my program all the time still send x"40" to DATA and it is propably connected with this counter which you were talking about.
There is my simulation efect. I becoming upset with that couse i don't have enough skills in vhdl to do it by my self. I hope that you will help me to do rebuild my project. On simulation it looks good i dont know how it looks on Xilinx.
Can you show me a piece of code? - Stefan
The entire purpose to providing the link to Adrian Adamcyzk's code (Altera FPGA hardware (has an issue) vs ModelSim simulation (ok) - self implemented UART) was to provide an example with a bit (baud) counter and flip flop used to control sending the message once.
Here's Jackob's modified:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity uartbyjackob is
port (
clk, a, b, c: in std_logic;
reset: in std_logic;
txd, txdosc: out std_logic
);
end entity uartbyjackob;
architecture foo of uartbyjackob is
-- signal k: unsigned(14 downto 0); -- FOR simulation
-- note if k were used in simulation it would require initialization
signal q: unsigned (3 downto 0); -- WAS std_logic_vector
signal clk_txd: std_logic;
signal enable: std_logic;
signal qtxd: std_logic_vector(9 downto 0);
-- signal data: std_logic_vector(7 downto 0);
-- added:
signal bdcnt: unsigned (3 downto 0);
signal ldqtxd: std_logic;
signal davl: std_logic;
type data_lut is array (0 to 15) of std_logic_vector (7 downto 0);
constant data: data_lut := (
x"40", x"41", x"42", x"43", x"44", x"45", x"46", x"47",
x"48", x"49", x"50", X"51", x"52", X"53", x"54", x"55"
);
signal datalut: std_logic_vector (7 downto 0); -- FOR SIMULATION visibility
begin
-- -- freq of clock -- NOTE k never in known binary state for simulation
-- process (clk, reset)
-- begin
-- if rising_edge(clk) then
-- if a = '1' and k < 10416 then
-- k <= k + 1;
-- clk_txd <= k(13);
-- elsif b = '1' and k < 5208 then
-- k <= k + 1;
-- clk_txd <= k(12);
-- elsif c = '1' and k < 20832 then
-- k <= k + 1;
-- clk_txd <= k(14);
-- else
-- k <= (others => '0');
-- end if;
-- end if;
-- end process;
clk_txd <= clk; -- SHORTENS SIMULATION
DAVL_FF: -- DATA_AVAILABLE to send
process (clk_txd, reset)
begin
if reset = '1' then
davl <= '0';
elsif rising_edge (clk_txd) then
if q = 15 and bdcnt = 9 then -- a JK FF equivalent
davl <= '0';
elsif q = 0 then
davl <= '1'; -- one clock holderover from reset
-- else
-- davl <= davl;
end if;
end if;
end process;
-- process(clk_txd, reset, enable)
-- begin
-- if reset = '1' and enable = '0' then
-- q <= "0000";
-- elsif rising_edge(clk_txd) then
-- q <= q + 1;
-- end if;
-- end process;
QCNT:
process (clk_txd, reset)
begin
if reset = '1' then
q <= (others => '0');
elsif rising_edge (clk_txd) then
if enable = '1' then
q <= q + 1;
end if;
end if;
end process;
BAUD_COUNTER:
process (clk_txd, reset)
begin
if reset = '1' then
bdcnt <= (others => '0');
elsif rising_edge (clk_txd) then
if davl = '0' or bdcnt = 9 then
bdcnt <= (others => '0');
else
bdcnt <= bdcnt + 1;
end if;
end if;
end process;
-- comparator
-- enable <= '1' when (q > 4) else '0';
enable <= '1' when bdcnt = 9 and davl = '1' and q /= 15 else
'0';
-- q latches at 15;
ldqtxd <= '1' when bdcnt = 9 and davl = '1' else
'0';
datalut <= data(to_integer(q)); -- FOR SIMULATION VISIBILITIY
--transcoder
-- process(q, clk_txd)
-- begin
-- if rising_edge(clk_txd) then
-- case q is
-- when "0001" => data <= x"40";
-- when "0010" => data <= x"41";
-- when "0011" => data <= x"42";
-- when "0100" => data <= x"43";
-- when "0101" => data <= x"44";
-- when "0110" => data <= x"45";
-- when "0111" => data <= x"46";
-- when "1000" => data <= x"47";
-- when "1001" => data <= x"48";
-- when "1010" => data <= x"49";
-- when "1011" => data <= x"50";
-- when "1100" => data <= x"51";
-- when "1101" => data <= x"52";
-- when "1110" => data <= x"53";
-- when "1111" => data <= x"54";
-- when others => data <= x"55";
-- end case;
-- end if;
-- end process;
-- uart
-- process (clk_txd, enable, data)
-- begin
-- if enable = '0' then
-- qtxd <= data & "01";
-- elsif rising_edge(clk_txd) then
-- qtxd <= '1' & qtxd(9 downto 1);
-- end if;
-- end process;
TX_SHIFT_REG:
process (clk_txd, reset) -- shift regiseter Tx UART
begin
if reset = '1' then
qtxd <= (others => '1'); -- output mark by default
elsif rising_edge (clk_txd) then
if ldqtxd = '1' then
qtxd <= '1' & data(to_integer(q)) & '0';
-- STOP & Data(q) 7 downto 0 & START , a MUX and expansion
else
qtxd <= '1' & qtxd(9 downto 1); -- shift out;
end if;
end if;
end process;
txd <= qtxd(0);
txdosc <= qtxd(0);
end architecture foo;
library ieee;
use ieee.std_logic_1164.all;
entity uartbyjackob_tb is
end entity;
architecture foo of uartbyjackob_tb is
signal clk: std_logic := '0';
signal reset: std_logic := '0';
signal txd: std_logic;
begin
DUT:
entity work.uartbyjackob
port map (
clk => clk, -- clk_txd driven by clk
a => 'X',
b => 'X',
c => 'X', -- a, b, c aren't used
reset => reset,
txd => txd,
txdosc => open
);
CLOCK:
process
begin
wait for 52.35 us;
clk <= not clk;
if now > 20000 us then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 104.7 us;
reset <= '1';
wait for 104.7 us;
reset <= '0';
wait;
end process;
end architecture;
The model has been modified for faster simulation, ignoring the baud rate clock generator.
There's an added flip flop (davl) for enabling the UART to run. There's an added baud (bit) counter bdcnt.
I changed the order of the start, stop and data values loaded into QTxD so the start bit came out first, followed by 8 data bits and the stop bit.
You can read off TxD from left to right start bit, data(q)(0) ... data(q(7), stop bit. The enable or ldqtxd will occur at the same time as a stop bit.
There's only one observable draw back to this implementation, if you reset while a value in the shift register hasn't finished loading you'll cause a framing error for the receiver. Don't reset it for 10 baud times after davl goes false.
The simulation is shown with a 9600 baud clk_txd, the characters go out back to back.
It has fewer flip flops than the original (disregarding k). There is no data register separate from QTxD ( - 8 FFs) plus bdcnt (+ 4) plus davl (+ 1). There are two comparisons (optimized to two) bdcnt = 9, q =, /= 9. Those could be expressed separately so it doesn't require optimization during synthesis.
I changed the look up table style, a matter of personal preference also the excuse for changing counters to type unsigned and using only package numeric_std for arithmetic.
The little testbench likewise doesn't expect the k counter to generate the baud clock.
Running the testbench gives:
Where there's an added signal datalut to show the value being shifted out after ldqtxd.
After your change making the q counter (7 downto 0)
We still see from your waveform that it doesn't work.
This is due to the enable and the shift register.
If you use a single counter with the upper four bits indexing the output character your character is transmitted in 10 out of the 16 clk_txd times indexed by the lower four bits of the counter. The remaining clock times TxD should be '1' (idle line marks in RS-232 parlance).
The order for data to be transmitted will be a space (the start bit), data(0) through data(7) and a mark (the stop bit). (Shown left to right on TxD).
For simulation the k counter is not used. I included it commented out below.
I made several changes for proper simulation. These include synchronously loading the shift register containing QTxD, synchronously clearing the rightmost bit of QTxD to provide a full width and moving enable to occur once every sixteen clocks (clk_txd). The enable is preceded by a new clear for the start bit and both been offset to prevent it from occurring during reset which has the effect of causing a framing error on the first character for any receiver.
Simulation is done with the same testbench I provide above.
The changes to your new code are shown by comments:
architecture behavioral of uartbyjackob is
-- signal k: std_logic_vector(14 downto 0);
signal q: unsigned (7 downto 0); -- std_logic_vector(7 downto 0);
signal clk_txd: std_logic;
signal enable: std_logic;
signal qtxd: std_logic_vector(7 downto 0);
-- using an 8 bit shift register requires a method of outputting a
-- synchronous start bit (the width is important for receive framing)
-- and synchronous stop bit
signal data: std_logic_vector(7 downto 0);
signal qprim: std_logic_vector(3 downto 0);
signal clear: std_logic; -- synchronous clear for start bit
begin
-- let's keep this here for when you put it the FPGA
-- -- freq of clock -- NOTE k never in known binary state for simulation
-- process (clk, reset)
-- begin
-- if rising_edge(clk then
-- if a = '1' and k < 10416 then
-- k <= k + 1;
-- clk_txd <= k(13);
-- elsif b = '1' and k < 5208 then
-- k <= k + 1;
-- clk_txd <= k(12);
-- elsif c = '1' and k < 20832 then
-- k <= k + 1;
-- clk_txd <= k(14);
-- else
-- k <= (others => '0');
-- end if;
-- end if;
-- end process;
process (clk) -- , reset)
begin
clk_txd <= clk; -- if simply a concurrent assignment statement this
end process; -- would look similar to the elaborated equivalent
-- process. The difference, no sensitivity list and
-- an explict wait on clk statement at the end.
-- This process wants to be removed and replaced by
-- the above commented out process for synthesis
process (clk_txd, reset) -- , reset, enable) -- enable a reset?
begin
-- if enable = '0' then
if reset = '1' then -- puts q counter in known state for simulation
q <= "00000000";
elsif rising_edge(clk_txd) then
if q /= 255 then -- stop after sending once
q <= q + 1;
end if;
end if;
end process;
-- enable <= '1' when q <= 255 else '0'; -- this appears incorrect
enable <= '1' when q(3 downto 0) = "0010" else
'0';
clear <= '1' when q(3 downto 0) = "0001" else
'0';
-- USING ONE COUNTER requires some clocks output MARKS
-- (idle bits) each 16 clocks. It requires the load (enable)
-- occur once every 16 clocks.
-- q(3 downto 0) is selected for enable to prevent outputting spaces
-- TxD during reset (q is reset to all '0's). This would cause a receive
-- framing error.
process (q(7 downto 4))
begin
case q(7 downto 4) is
when "0000" => data <= x"40";
when "0001" => data <= x"41";
when "0010" => data <= x"42";
when "0011" => data <= x"43";
when "0100" => data <= x"44";
when "0101" => data <= x"45";
when "0110" => data <= x"46";
when "0111" => data <= x"47";
when "1000" => data <= x"48";
when "1001" => data <= x"49";
when "1010" => data <= x"50";
when "1011" => data <= x"51";
when "1100" => data <= x"52";
when "1101" => data <= x"53";
when "1110" => data <= x"54";
when "1111" => data <= x"55";
when others => data <= x"56";
end case;
end process;
process (clk_txd) -- , enable, data) -- synchronous enable and clear
begin
-- if enable = '1' then -- this appears incorrect
-- qtxd <= data;
if reset = '1' then
qtxd <= (others => '1'); -- outputs mark after reset
elsif rising_edge(clk_txd) then
if clear = '1' then -- synchronous clear for start bit
qtxd(0) <= '0';
elsif enable = '1' then -- synchronous load
qtxd <= data;
else
qtxd <= '1' & qtxd(7 downto 1); -- shift right
end if;
end if;
end process;
-- the synchronous load prevents the first start bit from being stretched
-- q(3 downto 0) the following in hex notation
-- q(3 downto 0) = 2 is the start bit
-- = 3 is data(0)
-- ...
-- = A is data(7)
-- = B is the stop bit
-- = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
-- = 1 enable occurs loading qtxd
--
-- The offset is caused by synchronous load (1 clk_txd) and the load point
-- (q(3 downto 0) = 1 in enable term).
--
-- The load point wants to occur in the first 6 counts of q(3 downto 0) to
-- insure a trailing mark when q is stopped.
--
-- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces
-- during reset from causing a receive framing error.
txd <= qtxd(0);
txdosc <= qtxd(0);
end architecture behavioral;
The comment table:
-- the synchronous load prevents the first start bit from being stretched
-- q(3 downto 0) the following in hex notation
-- q(3 downto 0) = 2 is the start bit
-- = 3 is data(0)
-- ...
-- = A is data(7)
-- = B is the stop bit
-- = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
-- = 1 enable occurs loading qtxd
--
-- The offset is caused by synchronous load (1 clk_txd) and the load point
-- (q(3 downto 0) = 1 in enable term).
--
-- The load point wants to occur in the first 6 counts of q(3 downto 0) to
-- insure a trailing mark when q is stopped.
--
-- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces
-- during reset from causing a receive framing error.
tells you where to find bits of the data(q(7 downto 0)) selected character. In the following waveform q is shown as hex to match:
You'll find with the fixes the first character transmitted is 0x40, the second 0x41,...
I'm going to implement partial reconfiguration on virtex5 Xilinx Board. I've written 3 modules(top module and up-counter and down-counter) and created bit streams by Plan-ahead.The result is shown by 2 LEDs(up or down count). My problem is how to exchange counter partitions? or how to control icap by time or an external signal?
I prefer to don't use Microblaze so write state machine for icap as below:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_arith.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
library UNISIM;
use UNISIM.VComponents.all;
Library UNIMACRO;
use UNIMACRO.vcomponents.all;
entity Main is
port(
Clk: in std_logic;
Output: out std_logic_vector(2 downto 0)
);
end Main;
architecture Behavioral of Main is
signal Q: std_logic_vector(47 downto 0);
signal Load, Clk1hz, Clk1 : std_logic;
signal Local : std_logic_vector(1 downto 0);
component ROM ------------------------------ ROM Component Decleration
port (
Clka: in std_logic;
Addra: in std_logic_vector(11 downto 0);
Douta: out std_logic_vector(31 downto 0));
end component; -------------------------------------------------------End
signal ROM_Address, ROM_Address_Init : std_logic_vector(11 downto 0); -------- ROM and ICAP Signals Decleration
signal ROM_Data : std_logic_vector(31 downto 0);
signal ICAP_Din, ICAP_Dout : std_logic_vector(31 downto 0);
signal ICAP_CE, ICAP_Clk, ICAP_Clk1, En, ROM_Clk, ROM_Clk1, ICAP_WR : std_logic; --------------------------------------End
begin
Clk1Hz <= Clk1;
process(clk)
begin
if (rising_edge(Clk)) then
if (Q=x"000005F5E100") then
Load <= '1';
Clk1 <= not Clk1;
else
Load <= '0';
end if;
end if;
end process;
Output(0) <= not(En);
Output(2 downto 1) <= not(Local);
----------------------------------------------------
----------------------------------------------------
U_UpDown: entity work.Counter
port map(
Clk => Clk1Hz, En => '1', Output => Local
);
----------------------------------------------------
----------------------------------------------------
U1 : COUNTER_LOAD_MACRO
generic map (
COUNT_BY => X"000000000001", -- Count by value
DEVICE => "VIRTEX5", -- Target Device: "VIRTEX5", "VIRTEX6", "SPARTAN6"
WIDTH_DATA => 48) -- Counter output bus width, 1-48
port map (
Q => Q, -- Counter output, width determined by WIDTH_DATA generic
CLK => CLK, -- 1-bit clock input
CE => '1', -- 1-bit clock enable input
DIRECTION => '1', -- 1-bit up/down count direction input, high is count up
LOAD => LOAD, -- 1-bit active high load input
LOAD_DATA => x"000000000000", -- Counter load data, width determined by WIDTH_DATA generic
RST => '0' -- 1-bit active high synchronous reset
);
--------------------------------------------
--------------------------------------------
process(Clk1Hz) -------------------------------------------- ROM and ICAP Modules and Related Codes
variable Count : integer range 0 to 6:=0;
begin
if (rising_edge(Clk1Hz)) then
Count := Count + 1;
if (Count = 2) then
En <= '1';
ROM_Address_Init <= conv_std_logic_vector(0,12);
else
En <= '0';
end if;
end if;
end process;
--------------------------------------------
--------------------------------------------
U_ROM: ROM
port map (Clka => ROM_Clk1, Addra => ROM_Address, Douta => ROM_Data);
BUFG_inst : BUFG
port map (
O => ROM_Clk1, -- Clock buffer output
I => ROM_Clk -- Clock buffer input
);
BUFG_inst1 : BUFG
port map (
O => ICAP_Clk1, -- Clock buffer output
I => ICAP_Clk -- Clock buffer input
);
ICAP_VIRTEX5_inst : ICAP_VIRTEX5
generic map (
ICAP_WIDTH => "X32") -- "X8", "X16" or "X32"
port map (
BUSY => open, -- Busy output
O => ICAP_Dout, -- 32-bit data output
CE => ICAP_CE, -- Clock enable input
CLK => ICAP_Clk1, -- Clock input
I => ICAP_Din, -- 32-bit data input
WRITE => ICAP_WR -- Write input
);
-- ICAP_Din(31 downto 8) <= x"000000"; -------------------------------End
U_ICAP_SM: block -------------------------------------
type State_Type is (State0, State00, State1, State2, State3, State4, State5, State6);
signal Pr_State, Nx_State : State_Type;
begin
Process(En,Clk)
begin
if (En = '0') then
Pr_State <= State0;
elsif (rising_edge(Clk)) then
Pr_State <= Nx_State;
end if;
end process;
process(Pr_State)
begin
case Pr_State is --*****
when State0 =>
Nx_State <= State00;
ROM_Address <= x"000";
ICAP_WR <= '1';
ROM_Clk <= '0';
ICAP_Clk <= '0';
ICAP_CE <= '1';
when State00 =>
Nx_State <= State1;
ICAP_WR <= '0';
when State1 =>
Nx_State <= State2;
ICAP_CE <= '0';
ROM_Clk <= '1';
when State2 =>
Nx_State <= State3;
ICAP_Din <= ROM_Data;
ROM_Clk <= '0';
when State3 =>
Nx_State <= State4;
ICAP_Clk <= '1';
when State4 =>
Nx_State <= State5;
ICAP_Clk <= '0';
when State5 =>
if (ROM_Address = conv_std_logic_vector(3134,12)) then
Nx_State <= State6;
ICAP_CE <= '1';
ROM_Address <= X"000";
else
Nx_State <= State1;
ROM_Address <= (ROM_Address + 1);
end if;
when State6 =>
ICAP_WR <= '1';
end case;
end process;
end Block U_ICAP_SM; -----------------------------------
end Behavioral;
I saved the bit stream (.coe file) of one of the counter (for example up-counter) in ROM. By default circuit is down counting, but when I exchange bit stream by icap (load .coe file of up-counter from ROM) nothing happens and circuit is counting down. (***** in the code)
how can I fix it?
I wrote this VHDL-program vor an ALU and its testbench that is working:
ALU-code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ALU_CLK is
port( Clk : in std_logic; --clock signal
InRegA,InRegB : in signed(31 downto 0); --input operands
InOp : in unsigned(2 downto 0); --Operation to be performed
OutReg : out signed(31 downto 0); --output of ALU
OutZero : out std_logic
);
end ALU_CLK;
architecture Behavioral of ALU_CLK is
signal Reg1,Reg2,Reg3 : signed(31 downto 0) := (others => '0');
begin
Reg1 <= INregA;
Reg2 <= InRegB;
OutReg <= Reg3;
process(Clk)
variable temp: signed(31 downto 0);
begin
if(rising_edge(Clk)) then
case InOp is
when "010" =>
temp := Reg1 + Reg2; --addition
when "000" =>
temp := Reg1 and Reg2; --AND gate
when "001" =>
temp := Reg1 or Reg2; --OR gate
when others =>
NULL;
end case;
if temp = (31 downto 0=>'0') then
OutZero <= '1';
else
OutZero <= '0';
end if;
Reg3 <= temp;
end if;
end process;
end Behavioral;
The testbench code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE ALU_CLK OF tb IS
signal Clk : std_logic := '0';
signal A,B,R : signed(31 downto 0) := (others => '0');
signal Op : unsigned(2 downto 0) := (others => '0');
signal zero : std_logic :='0';
constant Clk_period : time := 10 ns;
BEGIN
uut: entity work.ALU_CLK PORT MAP (
Clk => Clk,
InRegA => A,
InRegB => B,
InOp => Op,
OutReg => R,
OutZero => zero
);
Clk_process :process
begin
Clk <= '0';
wait for Clk_period/2;
Clk <= '1';
wait for Clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
wait for Clk_period*1;
--test normal operations
A <= "00000000000000000000000000010011"; --19 in decimal
B <= "00000000000000000000000000001100"; --12 in decimal
Op <= "000"; wait for Clk_period; --Bitwise and A and B
Op <= "001"; wait for Clk_period; --Bitwise or B from A.
Op <= "010"; wait for Clk_period; --addition A nad B
wait;
end process;
END;
To shorten the code listings a bit I did not post all the operations the ALU does.
I can manage it to change the ALU to one without the clk but how can I test it with a testbench?
Even in a test bench for a module without a clock, it may be a good idea to have
a clock that can time the test events, and make it easier to see the test
progress in waveforms.
So after removal of the clock from the ALU, the test bench process can control
stimuli and do the checks like:
-- Combined stimuli and check process
process is
begin
...
-- === 2 + 2 test ===
-- Stimuli control
wait until rising_edge(clk);
InRegA <= to_signed(2, InRegA'length);
InRegB <= to_signed(2, InRegA'length);
InOp <= "010"; -- Add
-- Output check
wait until falling_edge(clk);
assert OutReg = InRegA + InRegB;
assert (OutZero = '1') = (OutReg = 0);
...
end process;
To simplify the check part, it can be moved to a separate process and the check
can be made depending on the operation like:
-- Check process
process (clk) is
begin
if falling_edge(clk) then
if check then
-- OutReg check
case InOp is
when "010" => assert OutReg = InRegA + InRegB; -- Add
when "000" => assert OutReg = (InRegA and InRegB); -- And
when "001" => assert OutReg = (InRegA or InRegB); -- Or
when others => report "Unsupported operation" severity ERROR;
end case;
-- OutZero check
assert (OutZero = '1') = (OutReg = 0);
end if;
end if;
end process;
The check signal is controlled by the stimuli process, to guard when the
check is to be made, in order to avoid false errors in startup or for other
special conditions.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity alu32bit is
port(en:in STD_LOGIC;
opc:in STD_LOGIC_VECTOR(3 downto 0);
a_in,b_in:in STD_LOGIC_VECTOR(31 downto 0);
y_op:out STD_LOGIC_VECTOR(31 downto 0));
end alu32 bit;
architecture Behavioral of alu32 bit is
begin
Process(en,a_in,b_in,opc)
begin
if(en='1')then
when "0001"=>y_op<=a_in+b_in;
when "0010"=>y_op<=a_in-b_in;
when "0011"=>y_op<=not a_in;
when "0100"=>y_op<=a_in and b_in;
when "0101"=>y_op<=a_in or b_in;
when "0110"=>y_op<=a_in nand b_in;
when "0111"=>y_op<=a_in xor b_in;
when others=>null;
end case;
else
y_op<="ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
end if;
end process;
end Behavioral;
In the end I got this:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ALU_32 is
port(
InRegA,InRegB : in signed(31 downto 0); --input operands
InOp : in unsigned(2 downto 0); --Operation to be performed
OutReg : out signed(31 downto 0); --output of ALU
OutZero : out std_logic
);
end ALU_32;
architecture Behavioral of ALU_32 is
--temporary signal declaration.
signal Reg1,Reg2,Reg3 : signed(31 downto 0) := (others => '0');
begin
Reg1 <= InRegA;
Reg2 <= InRegB;
OutReg <= Reg3;
process(InOp, InRegA, inRegB)
variable temp: signed(31 downto 0);
begin
case InOp is
when "010" =>
temp := Reg1 + Reg2; --addition
when "110" =>
temp := Reg1 - Reg2; --subtraction
when "000" =>
temp := Reg1 and Reg2; --AND gate
when "001" =>
temp := Reg1 or Reg2; --OR gate
when "100" =>
temp := Reg1 nor Reg2; --NOR gate
when "011" =>
temp := Reg1 xor Reg2; --XOR gate
when "101" =>
temp := not Reg1; --NOT gate
when "111" =>
if Reg1 < Reg2 then --SLT (set on less than) gate
temp := (others => '1');
else
temp := (others => '0');
end if;
when others =>
NULL;
end case;
if temp = (31 downto 0=>'0') then
OutZero <= '1';
else
OutZero <= '0';
end if;
Reg3 <= temp;
end process;
end Behavioral;
And the working testbench is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
ENTITY tb2 IS
END tb2;
ARCHITECTURE ALU_32 OF tb2 IS
COMPONENT ALU_32
PORT(
InRegA : IN signed(31 downto 0);
InRegB : IN signed(31 downto 0);
InOp : IN unsigned(2 downto 0);
OutReg : OUT signed(31 downto 0);
OutZero : OUT std_logic
);
END COMPONENT;
--Inputs
signal InRegA : signed(31 downto 0) := (others => '0');
signal InRegB : signed(31 downto 0) := (others => '0');
signal InOp : unsigned(2 downto 0) := (others => '0');
--Outputs
signal OutReg : signed(31 downto 0);
signal OutZero : std_logic;
-- No clocks detected in port list. Replace <clock> below with
-- appropriate port name
--constant <InOp>_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: ALU_32 PORT MAP (
InRegA => InRegA,
InRegB => InRegB,
InOp => InOp,
OutReg => OutReg,
OutZero => OutZero
);
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
-- insert stimulus here
--test normal operations
InRegA <= "00000000000000000000000000010011"; --19 in decimal
InRegB <= "00000000000000000000000000001100"; --12 in decimal
InOp <= "000"; wait for 100 ns; --Bitwise and A and B
InOp <= "001"; wait for 100 ns; --Bitwise or B from A.
InOp <= "010"; wait for 100 ns; --addition A nad B
InOp <= "100"; wait for 100 ns; --Bitwise NOR of A and B
InOp <= "011"; wait for 100 ns; --Bitwise XOR of A and B
InOp <= "110"; wait for 100 ns; --substract A and B
InOp <= "101"; wait for 100 ns; --Bitwise NOT of A
InOp <= "111"; wait for 100 ns; --Bitwise SLT of A and B
-- test SLT the other way around
InRegB <= "00000000000000000000000000010011"; --19 in decimal
InRegA <= "00000000000000000000000000001100"; --12 in decimal
InOp <= "111"; wait for 100 ns; --Bitwise SLT of A and B
-- test Branch equal that substraction is 0 and zero is 1
InRegA <= "00000000000000000000000000001011"; --11 in decimal
InRegB <= "00000000000000000000000000001011"; --11 in decimal
InOp <= "110"; wait for 100 ns; --substract A and B
wait;
end process;
END;
Here is the result of the simulation: