0

I have the following code describing some registers:

    DCR_WR_REGS_P: process (CLK)
    begin
        if rising_edge(CLK) then
            if DCR_WRITE = '1' then
               if C_BASEADDR(0 to 6) = DCR_ABUS(0 to 6) then
                    case to_integer(unsigned(DCR_ABUS(7 to 9))) is
                       when REG_DMA_RD_ADDR_OFFS =>
                            dma_rd_addr_reg <= DCR_WR_DBUS (0 to DMA_RD_ADDR_SZ-1);                              
                       when REG_DMA_RD_LENG_OFFS =>
                            dma_rd_leng_reg <= DCR_WR_DBUS (0 to DMA_RD_LENG_SZ-1);
                            rd_dma_req <= '1';
                       -- more registers here...
                       when

                       when
                       ----------------------
                       when others =>
                    end case;
                end if;
            else
                if clear_rd_dma_req='1' then
                    rd_dma_req <='0';
                end if;
            end if;
        end if;
    end process DCR_WR_REGS_P;

This code works except for the fact that the clear_rd_dma_req is ignored when DCR_WRITE is active. So, can I somehow make the "if clear_rd_dma_req='1'" clause an independent one? I realize that I can create a separate process just for the rd_dma_req bit, but I am trying to avoid that as I have a few bits like that.

Here's a version with a separate process:

DCR_WR_REGS_P: process (CLK)
begin
    if rising_edge(CLK) then
        if DCR_WRITE = '1' then
           if C_BASEADDR(0 to 6) = DCR_ABUS(0 to 6) then
                case to_integer(unsigned(DCR_ABUS(7 to 9))) is
                   when REG_DMA_RD_ADDR_OFFS =>
                        dma_rd_addr_reg <= DCR_WR_DBUS (0 to DMA_RD_ADDR_SZ-1);                              
                   when REG_DMA_RD_LENG_OFFS =>
                        dma_rd_leng_reg <= DCR_WR_DBUS (0 to DMA_RD_LENG_SZ-1);
                   -- more registers here...
                   when

                   when
                   ----------------------
                   when others =>
                end case;
            end if;
        end if;
    end if;
end process DCR_WR_REGS_P;

RD_DMA_REQ_P: process (CLK)
begin
    if rising_edge(CLK) then
        if clear_rd_dma_req='1' then
            rd_dma_req <='0';
        elsif DCR_WRITE = '1' then
            if C_BASEADDR(0 to 6) = DCR_ABUS(0 to 6) then
                if to_integer(unsigned(DCR_ABUS(7 to 9))) = REG_DMA_RD_LENG_OFFS then
                    rd_dma_req <= '1';
                end if;
            end if;
        end if;
    end if;
end process RD_DMA_REQ_P;

And here's a version with an independent if-clause, which is probably illegal:

    DCR_WR_REGS_P: process (CLK)
    begin
        if rising_edge(CLK) then
            if DCR_WRITE = '1' then
               if C_BASEADDR(0 to 6) = DCR_ABUS(0 to 6) then
                    case to_integer(unsigned(DCR_ABUS(7 to 9))) is
                       when REG_DMA_RD_ADDR_OFFS =>
                            dma_rd_addr_reg <= DCR_WR_DBUS (0 to DMA_RD_ADDR_SZ-1);                              
                       when REG_DMA_RD_LENG_OFFS =>
                            dma_rd_leng_reg <= DCR_WR_DBUS (0 to DMA_RD_LENG_SZ-1);
                            rd_dma_req <= '1';
                       -- more registers here...
                       when

                       when
                       ----------------------
                       when others =>
                    end case;
                end if;
            end if;
            if clear_rd_dma_req='1' then
                rd_dma_req <='0';
            end if;
        end if;
    end process DCR_WR_REGS_P;

Thanks

braX
  • 11,506
  • 5
  • 20
  • 33
mbmsv
  • 113
  • 3
  • The code in the section labeld "independent if-clause" is legal, and results in clear of `rd_dma_req` based on the "last assignment wins" rule as Brian Drummond wrote. Note however, that the code is different from the example code in Brians answer, since the reset based on `clear_rd_dma_req = '1'` only affects assign to `rd_dma_req`, where the `if ... elsif ...` style would prevent use of the `case` for assign to `dma_rd_addr_reg`, if the `case` is guarded by the `elsif`. – Morten Zilmer Dec 16 '15 at 22:03
  • Can there be an issue with synthesizing it? I think I that I had tried this in the past and it didn't synthesize correctly (using Xilinx XST), although I am not sure now... Thanks. – mbmsv Dec 17 '15 at 05:10
  • It ought to synthesize correctly, and the construction is widely used, so just go ahead. – Morten Zilmer Dec 17 '15 at 07:17

1 Answers1

2

Yes you can make it an independent one (still inside the if rising_edge(clk) statement). What makes you think this version (last in the modified question) should be illegal?

Anything it does will override assignments made to the same signals by the if DCR_Write statement, thanks to the "last assignment wins" rule.

HOWEVER why not simply reverse the prioritisation and tidy it up, like this?

if clear_rd_dma_req='1' then
   ...
elsif DCR_Write = '1' then
   ... 
end if;
  • Well, when I said independent I meant no elsif's. The problem here is that I have more than one bit to clear. For now I've decided to create separate processes for each of them but I am still curious if there is a compact way of describing this. – mbmsv Dec 16 '15 at 16:13
  • @mbmsv: Please show the code with "separate processes" and no `elsif`; so we may give a suggestion for a compact form for the relevant code. – Morten Zilmer Dec 16 '15 at 18:06
  • I have edited the original question as requested. Thanks. – mbmsv Dec 16 '15 at 18:57